diff --git a/upvpn-apple/UpVPN/App/Views/Color+Extension.swift b/upvpn-apple/UpVPN/App/Views/Color+Extension.swift index 0ab7957..b7c0b27 100644 --- a/upvpn-apple/UpVPN/App/Views/Color+Extension.swift +++ b/upvpn-apple/UpVPN/App/Views/Color+Extension.swift @@ -12,6 +12,8 @@ extension Color { static var uSystemGroupedBackground: Color { #if os(iOS) return Color(uiColor: .systemGroupedBackground) + #elseif os(tvOS) + return Color(uiColor: .clear) #elseif os(macOS) return Color.clear #endif @@ -20,6 +22,8 @@ extension Color { static var uSecondarySystemGroupedBackground: Color { #if os(iOS) return Color(uiColor: .secondarySystemGroupedBackground) + #elseif os(tvOS) + return Color(uiColor: .clear) #elseif os(macOS) return Color(nsColor: .controlBackgroundColor) #endif diff --git a/upvpn-apple/UpVPN/App/Views/FlagImage.swift b/upvpn-apple/UpVPN/App/Views/FlagImage.swift index 4214a40..cdbd36c 100644 --- a/upvpn-apple/UpVPN/App/Views/FlagImage.swift +++ b/upvpn-apple/UpVPN/App/Views/FlagImage.swift @@ -14,6 +14,11 @@ struct FlagImage: View { var body: some View { #if os(iOS) Image(uiImage: Flag(countryCode: countryCode)!.image(style: .roundedRect)) + #elseif os(tvOS) + Image(uiImage: Flag(countryCode: countryCode)!.image(style: .roundedRect)) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(minWidth: 50, maxWidth: 50) #elseif os(macOS) Image(nsImage: Flag(countryCode: countryCode)!.originalImage) .clipShape(RoundedRectangle(cornerRadius: 3)) diff --git a/upvpn-apple/UpVPN/App/Views/KeyValueView.swift b/upvpn-apple/UpVPN/App/Views/KeyValueView.swift index eea9df8..d05ca06 100644 --- a/upvpn-apple/UpVPN/App/Views/KeyValueView.swift +++ b/upvpn-apple/UpVPN/App/Views/KeyValueView.swift @@ -17,7 +17,9 @@ struct KeyValueView: View { Text(value) .lineLimit(1) .opacity(0.5) + #if !os(tvOS) .textSelection(.enabled) + #endif } } } diff --git a/upvpn-apple/UpVPN/App/Views/LocationsMapView.swift b/upvpn-apple/UpVPN/App/Views/LocationsMapView.swift index 1b97881..82a6078 100644 --- a/upvpn-apple/UpVPN/App/Views/LocationsMapView.swift +++ b/upvpn-apple/UpVPN/App/Views/LocationsMapView.swift @@ -102,7 +102,12 @@ struct LocationsMapView: View { if let coordinate = getCoordinate(location) { Annotation("", coordinate: coordinate) { LocationView(location: location) + .id(locationViewModel.locationsLastUpdated) + #if os(tvOS) + .background(.ultraThinMaterial) + #else .background(Color.uSecondarySystemGroupedBackground) + #endif .clipShape(RoundedRectangle(cornerRadius: 10)) .environmentObject(locationViewModel) } diff --git a/upvpn-apple/UpVPN/App/Views/Plan/PrepaidPlansView.swift b/upvpn-apple/UpVPN/App/Views/Plan/PrepaidPlansView.swift index ce12f25..acc0dae 100644 --- a/upvpn-apple/UpVPN/App/Views/Plan/PrepaidPlansView.swift +++ b/upvpn-apple/UpVPN/App/Views/Plan/PrepaidPlansView.swift @@ -14,10 +14,14 @@ struct PrepaidPlansView: View { var selectedProduct: Product? = nil var setSelectedProduct: (Product) -> Void + #if os(tvOS) + private let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: 40), count: 4) + #else private let columns = [ GridItem(.fixed(120)), GridItem(.fixed(120)) ] + #endif var body: some View { Group { diff --git a/upvpn-apple/UpVPN/App/Views/RuntimeConfigurationView.swift b/upvpn-apple/UpVPN/App/Views/RuntimeConfigurationView.swift index 8b637cf..bc12319 100644 --- a/upvpn-apple/UpVPN/App/Views/RuntimeConfigurationView.swift +++ b/upvpn-apple/UpVPN/App/Views/RuntimeConfigurationView.swift @@ -46,6 +46,12 @@ struct RuntimeConfigurationView: View { .localizedString(for: lastHandshakeTime, relativeTo: Date())) } } + #if os(tvOS) + // so that list can scroll on tvOS + .focusable() + #endif + // otherwise list does not update + .onReceive(tunnelViewModel.tunnelObserver.$runtimeConfig) { _ in } } } #if os(iOS) diff --git a/upvpn-apple/UpVPN/Common/FileManager+Extension.swift b/upvpn-apple/UpVPN/Common/FileManager+Extension.swift index c671d81..fadc702 100644 --- a/upvpn-apple/UpVPN/Common/FileManager+Extension.swift +++ b/upvpn-apple/UpVPN/Common/FileManager+Extension.swift @@ -15,6 +15,8 @@ extension FileManager { static var appGroupId: String? { #if os(iOS) let appGroupIdInfoDictionaryKey = "app.upvpn.apple.ios.app_group_id" + #elseif os(tvOS) + let appGroupIdInfoDictionaryKey = "app.upvpn.apple.tvos.app_group_id" #elseif os(macOS) let appGroupIdInfoDictionaryKey = "app.upvpn.apple.macos.app_group_id" #else @@ -28,10 +30,19 @@ extension FileManager { os_log("Cannot obtain app group ID from bundle", log: OSLog.default, type: .error) return nil } - guard let sharedFolderURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupId) else { + guard let appGroupSharedFolderURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupId) else { os_log(.error, "Cannot obtain shared folder URL") return nil } + + var sharedFolderURL = appGroupSharedFolderURL + + #if os(tvOS) + // cannot write file in the folder, hence write in directory thats created by default inside app group container + // https://developer.apple.com/documentation/foundation/filemanager/1412643-containerurl#2851195 + sharedFolderURL = sharedFolderURL.appendingPathComponent("Library/Caches") + #endif + return sharedFolderURL } diff --git a/upvpn-apple/UpVPN/Common/Keychain.swift b/upvpn-apple/UpVPN/Common/Keychain.swift index e373585..7496259 100644 --- a/upvpn-apple/UpVPN/Common/Keychain.swift +++ b/upvpn-apple/UpVPN/Common/Keychain.swift @@ -31,7 +31,7 @@ class Keychain { /// More info: https://developer.apple.com/forums/thread/133677?answerId=422887022#422887022 /// Hence on macOS we use keychain access group instead of app group static var keychainGroupId: String? { - #if os(iOS) + #if os(iOS) || os(tvOS) return FileManager.appGroupId #elseif os(macOS) let keychainGroupIdInfoDictionaryKey = "app.upvpn.apple.macos.keychain_group_id" diff --git a/upvpn-apple/UpVPN/Config/Version.xcconfig b/upvpn-apple/UpVPN/Config/Version.xcconfig index 1412ea6..0b7daff 100644 --- a/upvpn-apple/UpVPN/Config/Version.xcconfig +++ b/upvpn-apple/UpVPN/Config/Version.xcconfig @@ -1,2 +1,2 @@ -VERSION_NAME = 1.0.0 -VERSION_ID = 5 +VERSION_NAME = 1.0.1 +VERSION_ID = 8 diff --git a/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.pbxproj b/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.pbxproj index 3ca56b4..9d5f45a 100644 --- a/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.pbxproj +++ b/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + A3212C1E2C8D69C5005E7D3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A3212C1D2C8D69C5005E7D3D /* Assets.xcassets */; }; + A3212C212C8D69C5005E7D3D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A3212C202C8D69C5005E7D3D /* Preview Assets.xcassets */; }; A323FAE52C57FD4C00CF9D84 /* ElapsedTimeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAE42C57FD4C00CF9D84 /* ElapsedTimeView.swift */; }; A323FAE62C57FD4C00CF9D84 /* ElapsedTimeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAE42C57FD4C00CF9D84 /* ElapsedTimeView.swift */; }; A323FAE82C580F0D00CF9D84 /* HomeCardDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAE72C580F0D00CF9D84 /* HomeCardDivider.swift */; }; @@ -49,6 +51,19 @@ A33336D82C47B937004D8C8E /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336D62C47B937004D8C8E /* Utils.swift */; }; A33336D92C47B937004D8C8E /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336D62C47B937004D8C8E /* Utils.swift */; }; A33336DA2C47B937004D8C8E /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336D62C47B937004D8C8E /* Utils.swift */; }; + A33E30632C968EE0001C0E89 /* LocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30622C968EDA001C0E89 /* LocationView.swift */; }; + A33E30652C969BB7001C0E89 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30642C969BB7001C0E89 /* HomeView.swift */; }; + A33E30672C96B210001C0E89 /* HomeCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30662C96B201001C0E89 /* HomeCard.swift */; }; + A33E30692C96B8AA001C0E89 /* VPNSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30682C96B8A4001C0E89 /* VPNSwitch.swift */; }; + A33E306B2C96C660001C0E89 /* StatsCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E306A2C96C65D001C0E89 /* StatsCard.swift */; }; + A33E306D2C971BE8001C0E89 /* PriceCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E306C2C971BE3001C0E89 /* PriceCapsule.swift */; }; + A33E30712C972E11001C0E89 /* PrepaidPlansView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3FABF8E2C6B2507004753D1 /* PrepaidPlansView.swift */; }; + A33E30732C973C8A001C0E89 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30722C973C88001C0E89 /* HelpView.swift */; }; + A33E30752C973FED001C0E89 /* LocationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30742C973FE9001C0E89 /* LocationsView.swift */; }; + A33E30772C97D52A001C0E89 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33E30762C97D528001C0E89 /* LoginView.swift */; }; + A33E307B2C97E4A7001C0E89 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A33E307A2C97E4A7001C0E89 /* LaunchScreen.storyboard */; }; + A33E307C2C992171001C0E89 /* CardContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAF62C5963CD00CF9D84 /* CardContainer.swift */; }; + A33E307D2C9925A4001C0E89 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A3CD54562C76BA1D00B7848E /* PrivacyInfo.xcprivacy */; }; A3422DBC2C2E448E00A3D867 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DBB2C2E448E00A3D867 /* TunnelViewModel.swift */; }; A3422DBD2C2E448E00A3D867 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DBB2C2E448E00A3D867 /* TunnelViewModel.swift */; }; A3422DC82C3562B700A3D867 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DC72C3562B700A3D867 /* Location.swift */; }; @@ -109,6 +124,69 @@ A350DF1F2C251E2A00BA1BA6 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A350DF0C2C251E0B00BA1BA6 /* NetworkExtension.framework */; }; A350DF272C251E2A00BA1BA6 /* UpVPNNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A350DF1E2C251E2A00BA1BA6 /* UpVPNNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; A350DF2C2C251F6100BA1BA6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A350DF0F2C251E0C00BA1BA6 /* PacketTunnelProvider.swift */; }; + A361CA302C94BAA000EB2CA3 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A350DF0C2C251E0B00BA1BA6 /* NetworkExtension.framework */; }; + A361CA382C94BAA000EB2CA3 /* UpVPNNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A361CA2F2C94BAA000EB2CA3 /* UpVPNNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + A361CA422C94D04A00EB2CA3 /* VPNState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DD82C387A8100A3D867 /* VPNState.swift */; }; + A361CA432C94D04A00EB2CA3 /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336B52C463394004D8C8E /* FileManager+Extension.swift */; }; + A361CA442C94D04A00EB2CA3 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336BD2C475E2C004D8C8E /* Keychain.swift */; }; + A361CA452C94D04A00EB2CA3 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336D62C47B937004D8C8E /* Utils.swift */; }; + A361CA462C94D04A00EB2CA3 /* AppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7635B2C4EF5B00088D5F5 /* AppConfig.swift */; }; + A361CA472C94D04A00EB2CA3 /* DeviceStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336C32C479C0E004D8C8E /* DeviceStore.swift */; }; + A361CA482C94D04A00EB2CA3 /* StoreKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336CD2C47A158004D8C8E /* StoreKeys.swift */; }; + A361CA492C94D04A00EB2CA3 /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9892C4919FA0008D23F /* UserStore.swift */; }; + A361CA4A2C94D04A00EB2CA3 /* StoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D98E2C4939F90008D23F /* StoreError.swift */; }; + A361CA4B2C94D04A00EB2CA3 /* LocationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A763722C521EF80088D5F5 /* LocationStore.swift */; }; + A361CA4C2C94D04A00EB2CA3 /* DataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9A62C4979080008D23F /* DataRepository.swift */; }; + A361CA4D2C94D04A00EB2CA3 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DCD2C3879FD00A3D867 /* Request.swift */; }; + A361CA4E2C94D04A00EB2CA3 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DD22C387A0600A3D867 /* Response.swift */; }; + A361CA4F2C94D04A00EB2CA3 /* AppMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DDD2C387B0E00A3D867 /* AppMessageHandler.swift */; }; + A361CA502C94D04A00EB2CA3 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DC72C3562B700A3D867 /* Location.swift */; }; + A361CA512C94D04A00EB2CA3 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336C82C479D9F004D8C8E /* Device.swift */; }; + A361CA522C94D04A00EB2CA3 /* UserCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9932C493A820008D23F /* UserCredentials.swift */; }; + A361CA532C94D04A00EB2CA3 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D99E2C4968130008D23F /* Types.swift */; }; + A361CA542C94D04A00EB2CA3 /* InterfaceConfiguration+Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F1062C708F6700AF1490 /* InterfaceConfiguration+Device.swift */; }; + A361CA552C94D04A00EB2CA3 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DF52C3F7F2100A3D867 /* Client.swift */; }; + A361CA562C94D04A00EB2CA3 /* VPNApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DFF2C3F802300A3D867 /* VPNApiService.swift */; }; + A361CA572C94D04A00EB2CA3 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A350DF0F2C251E0C00BA1BA6 /* PacketTunnelProvider.swift */; }; + A361CA582C94D04A00EB2CA3 /* VPNSessionWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422E0A2C3F8ADF00A3D867 /* VPNSessionWatcher.swift */; }; + A361CA592C94D04A00EB2CA3 /* VPNSessionRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A763602C50122C0088D5F5 /* VPNSessionRepository.swift */; }; + A361CA5A2C94D04A00EB2CA3 /* VPNSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7636C2C51877B0088D5F5 /* VPNSessionStore.swift */; }; + A361CA5B2C94D04A00EB2CA3 /* VPNSessionReclaimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7636F2C5196750088D5F5 /* VPNSessionReclaimer.swift */; }; + A361CA5C2C94D04A00EB2CA3 /* OrcestratorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DEE2C3E8D7B00A3D867 /* OrcestratorCommand.swift */; }; + A361CA5D2C94D04A00EB2CA3 /* VPNOrchestrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DEB2C3E8D4700A3D867 /* VPNOrchestrator.swift */; }; + A361CA5E2C94D04A00EB2CA3 /* VPNOrchestratorState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A763632C501B210088D5F5 /* VPNOrchestratorState.swift */; }; + A361CA5F2C94D04A00EB2CA3 /* ErrorNotifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336BA2C464079004D8C8E /* ErrorNotifier.swift */; }; + A361CA602C94D04A00EB2CA3 /* TunnelConfigurationExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A763662C509C0E0088D5F5 /* TunnelConfigurationExtension.swift */; }; + A361CA612C94D04A00EB2CA3 /* WGAdapterAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DF12C3EA41100A3D867 /* WGAdapterAsync.swift */; }; + A361CA632C94D06200EB2CA3 /* WireGuardKit in Frameworks */ = {isa = PBXBuildFile; productRef = A361CA622C94D06200EB2CA3 /* WireGuardKit */; }; + A361CA652C94D0BA00EB2CA3 /* WireGuardKit in Frameworks */ = {isa = PBXBuildFile; productRef = A361CA642C94D0BA00EB2CA3 /* WireGuardKit */; }; + A361CA672C94D68E00EB2CA3 /* UpVPNApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A350DED82C25141200BA1BA6 /* UpVPNApp.swift */; }; + A361CA682C94E5E400EB2CA3 /* DeviceStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336C32C479C0E004D8C8E /* DeviceStore.swift */; }; + A361CA692C94E5E400EB2CA3 /* DataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9A62C4979080008D23F /* DataRepository.swift */; }; + A361CA6A2C94E5E400EB2CA3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DBB2C2E448E00A3D867 /* TunnelViewModel.swift */; }; + A361CA6B2C94E5E400EB2CA3 /* AuthViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D99B2C4954A00008D23F /* AuthViewModel.swift */; }; + A361CA6C2C94E5E400EB2CA3 /* LocationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7637A2C5225E00088D5F5 /* LocationViewModel.swift */; }; + A361CA6D2C94E5E400EB2CA3 /* PlanViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3FABF8B2C6B068A004753D1 /* PlanViewModel.swift */; }; + A361CA6E2C94E62700EB2CA3 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336C82C479D9F004D8C8E /* Device.swift */; }; + A361CA6F2C94E62700EB2CA3 /* UserCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9932C493A820008D23F /* UserCredentials.swift */; }; + A361CA702C94E62700EB2CA3 /* VPNApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DFF2C3F802300A3D867 /* VPNApiService.swift */; }; + A361CA712C94E62700EB2CA3 /* TunnelManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3E352D92C2E30B6008D0E30 /* TunnelManager.swift */; }; + A361CA722C94E62700EB2CA3 /* TunnelObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DE52C3DB4DE00A3D867 /* TunnelObserver.swift */; }; + A361CA732C94E6A600EB2CA3 /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9892C4919FA0008D23F /* UserStore.swift */; }; + A361CA742C94E6A600EB2CA3 /* StoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D98E2C4939F90008D23F /* StoreError.swift */; }; + A361CA752C94E6A600EB2CA3 /* LocationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A763722C521EF80088D5F5 /* LocationStore.swift */; }; + A361CA762C94E6A600EB2CA3 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DC72C3562B700A3D867 /* Location.swift */; }; + A361CA772C94E6A600EB2CA3 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D99E2C4968130008D23F /* Types.swift */; }; + A361CA782C94E6C200EB2CA3 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336BD2C475E2C004D8C8E /* Keychain.swift */; }; + A361CA792C94E6C200EB2CA3 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DF52C3F7F2100A3D867 /* Client.swift */; }; + A361CA7A2C94E72D00EB2CA3 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336D62C47B937004D8C8E /* Utils.swift */; }; + A361CA7B2C94E75200EB2CA3 /* StoreKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336CD2C47A158004D8C8E /* StoreKeys.swift */; }; + A361CA7C2C94E78000EB2CA3 /* AppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7635B2C4EF5B00088D5F5 /* AppConfig.swift */; }; + A361CA7D2C94E84C00EB2CA3 /* TunnelManagerSimulator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CD54532C7447A100B7848E /* TunnelManagerSimulator.swift */; }; + A361CA7E2C94E85900EB2CA3 /* TunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3E352DC2C2E3D9D008D0E30 /* TunnelStatus.swift */; }; + A361CA7F2C94E8AF00EB2CA3 /* VPNState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DD82C387A8100A3D867 /* VPNState.swift */; }; + A361CA802C94E8E200EB2CA3 /* InterfaceConfiguration+Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F1062C708F6700AF1490 /* InterfaceConfiguration+Device.swift */; }; + A361CA812C94E90300EB2CA3 /* PlanRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A380AA992C6308CF007E09A1 /* PlanRepository.swift */; }; A364B0B72C7EB9C500A82952 /* UserDataConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A364B0B62C7EB9C500A82952 /* UserDataConsent.swift */; }; A364B0B82C7EB9C500A82952 /* UserDataConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A364B0B62C7EB9C500A82952 /* UserDataConsent.swift */; }; A36565F82C52E5F900C2E748 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36565F72C52E5F900C2E748 /* TunnelConfiguration+UapiConfig.swift */; }; @@ -140,8 +218,39 @@ A365665B2C57072000C2E748 /* FlagKit in Frameworks */ = {isa = PBXBuildFile; productRef = A365665A2C57072000C2E748 /* FlagKit */; }; A365665D2C570B8C00C2E748 /* TunnelStatus+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A365665C2C570B8C00C2E748 /* TunnelStatus+Extension.swift */; }; A365665E2C570B8C00C2E748 /* TunnelStatus+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A365665C2C570B8C00C2E748 /* TunnelStatus+Extension.swift */; }; + A379AAE32C9509EF00BC55AA /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33336B52C463394004D8C8E /* FileManager+Extension.swift */; }; + A379AAE42C950BFA00BC55AA /* UIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F1032C70249700AF1490 /* UIUtils.swift */; }; + A379AAE92C950D4B00BC55AA /* MainContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A379AAE72C950D1A00BC55AA /* MainContentView.swift */; }; + A379AAEA2C950D7400BC55AA /* RuntimeConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F0F42C6E934300AF1490 /* RuntimeConfigurationView.swift */; }; + A379AAEC2C950DB900BC55AA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A365660D2C55700200C2E748 /* SettingsView.swift */; }; + A379AAEF2C950E2400BC55AA /* FlagImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAED2C5842A700CF9D84 /* FlagImage.swift */; }; + A379AAF02C950E4800BC55AA /* LocationsMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A21D8A2C87362E00600C2C /* LocationsMapView.swift */; }; + A379AAF12C950E6F00BC55AA /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A350DEDA2C25141200BA1BA6 /* ContentView.swift */; }; + A379AAF32C950E7D00BC55AA /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36566042C54613A00C2E748 /* WelcomeView.swift */; }; + A379AAF42C950EAF00BC55AA /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36565FE2C545F8F00C2E748 /* MainView.swift */; }; + A379AAF72C950EE600BC55AA /* Location+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36566532C57031600C2E748 /* Location+Extension.swift */; }; + A379AAF82C950EEB00BC55AA /* TunnelStatus+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A365665C2C570B8C00C2E748 /* TunnelStatus+Extension.swift */; }; + A379AAF92C950EF100BC55AA /* ElapsedTimeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAE42C57FD4C00CF9D84 /* ElapsedTimeView.swift */; }; + A379AAFC2C950F0600BC55AA /* Color+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAF02C58637A00CF9D84 /* Color+Extension.swift */; }; + A379AB002C950F2500BC55AA /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F0F72C6FE58300AF1490 /* AccountView.swift */; }; + A379AB012C950F2B00BC55AA /* SignOutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F0FA2C6FE59200AF1490 /* SignOutView.swift */; }; + A379AB022C950F3000BC55AA /* VersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F0FD2C6FEF0100AF1490 /* VersionView.swift */; }; + A379AB032C950F3400BC55AA /* KeyValueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A9F1002C701FA700AF1490 /* KeyValueView.swift */; }; + A379AB042C950F3B00BC55AA /* UserDataConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A364B0B62C7EB9C500A82952 /* UserDataConsent.swift */; }; + A379AB072C950F4800BC55AA /* YearlyPlanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3FABF942C6B3E3B004753D1 /* YearlyPlanView.swift */; }; + A379AB082C950F4C00BC55AA /* PurchaseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3FABF972C6B4C3B004753D1 /* PurchaseButton.swift */; }; + A379AB092C950F5000BC55AA /* PlanManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A347A8252C6129CC00FEF961 /* PlanManagement.swift */; }; + A379AB0A2C950F5400BC55AA /* PlanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3FABF9B2C6B4F02004753D1 /* PlanView.swift */; }; + A379AB0B2C950F8900BC55AA /* Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = A323FAF32C58699000CF9D84 /* Country.swift */; }; + A379AB0C2C95104100BC55AA /* String+ArrayConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36565FA2C52E87300C2E748 /* String+ArrayConversion.swift */; }; + A379AB122C951CB000BC55AA /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DCD2C3879FD00A3D867 /* Request.swift */; }; + A379AB132C951CBA00BC55AA /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DD22C387A0600A3D867 /* Response.swift */; }; + A379AB142C951CC000BC55AA /* AppMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DDD2C387B0E00A3D867 /* AppMessageHandler.swift */; }; + A379AB152C951CC400BC55AA /* NETunnelProviderSessionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3422DE82C3DE35100A3D867 /* NETunnelProviderSessionExtension.swift */; }; + A379AB162C951CE600BC55AA /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36565F72C52E5F900C2E748 /* TunnelConfiguration+UapiConfig.swift */; }; A380AA9A2C6308CF007E09A1 /* PlanRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A380AA992C6308CF007E09A1 /* PlanRepository.swift */; }; A380AA9B2C6308CF007E09A1 /* PlanRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A380AA992C6308CF007E09A1 /* PlanRepository.swift */; }; + A38864182C94EBC000E91A1D /* FlagKit in Frameworks */ = {isa = PBXBuildFile; productRef = A38864172C94EBC000E91A1D /* FlagKit */; }; A391D98A2C4919FA0008D23F /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9892C4919FA0008D23F /* UserStore.swift */; }; A391D98B2C4919FA0008D23F /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D9892C4919FA0008D23F /* UserStore.swift */; }; A391D98F2C4939F90008D23F /* StoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A391D98E2C4939F90008D23F /* StoreError.swift */; }; @@ -246,6 +355,20 @@ remoteGlobalIDString = A350DF1D2C251E2A00BA1BA6; remoteInfo = UpVPNNetworkExtensionmacOS; }; + A361CA362C94BAA000EB2CA3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A350DECD2C25141100BA1BA6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A361CA2E2C94BAA000EB2CA3; + remoteInfo = UpVPNNetworkExtensiontvOS; + }; + A361CA402C94CF4D00EB2CA3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A350DECD2C25141100BA1BA6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A3212BEB2C8D6450005E7D3D; + remoteInfo = WireGuardGoBridgetvOS; + }; A3AA4B192C256F69001135FD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A350DECD2C25141100BA1BA6 /* Project object */; @@ -285,9 +408,23 @@ name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; + A361CA3C2C94BAA000EB2CA3 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + A361CA382C94BAA000EB2CA3 /* UpVPNNetworkExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + A3212C172C8D69C4005E7D3D /* UpVPN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UpVPN.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A3212C1D2C8D69C5005E7D3D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A3212C202C8D69C5005E7D3D /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; A323FAE42C57FD4C00CF9D84 /* ElapsedTimeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElapsedTimeView.swift; sourceTree = ""; }; A323FAE72C580F0D00CF9D84 /* HomeCardDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCardDivider.swift; sourceTree = ""; }; A323FAEA2C58100A00CF9D84 /* HomeCardLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCardLocation.swift; sourceTree = ""; }; @@ -305,6 +442,16 @@ A33336C82C479D9F004D8C8E /* Device.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = ""; }; A33336CD2C47A158004D8C8E /* StoreKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKeys.swift; sourceTree = ""; }; A33336D62C47B937004D8C8E /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; + A33E30622C968EDA001C0E89 /* LocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationView.swift; sourceTree = ""; }; + A33E30642C969BB7001C0E89 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + A33E30662C96B201001C0E89 /* HomeCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCard.swift; sourceTree = ""; }; + A33E30682C96B8A4001C0E89 /* VPNSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNSwitch.swift; sourceTree = ""; }; + A33E306A2C96C65D001C0E89 /* StatsCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsCard.swift; sourceTree = ""; }; + A33E306C2C971BE3001C0E89 /* PriceCapsule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceCapsule.swift; sourceTree = ""; }; + A33E30722C973C88001C0E89 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = ""; }; + A33E30742C973FE9001C0E89 /* LocationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsView.swift; sourceTree = ""; }; + A33E30762C97D528001C0E89 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + A33E307A2C97E4A7001C0E89 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; A3422DBB2C2E448E00A3D867 /* TunnelViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelViewModel.swift; sourceTree = ""; }; A3422DC72C3562B700A3D867 /* Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = ""; }; A3422DCD2C3879FD00A3D867 /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; @@ -338,6 +485,11 @@ A350DF122C251E0C00BA1BA6 /* UpVPNNetworkExtension_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UpVPNNetworkExtension_iOS.entitlements; sourceTree = ""; }; A350DF1E2C251E2A00BA1BA6 /* UpVPNNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UpVPNNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; A350DF242C251E2A00BA1BA6 /* UpVPNNetworkExtension_macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UpVPNNetworkExtension_macOS.entitlements; sourceTree = ""; }; + A361CA2F2C94BAA000EB2CA3 /* UpVPNNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UpVPNNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + A361CA3D2C94BF9B00EB2CA3 /* UpVPNNetworkExtension_tvOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UpVPNNetworkExtension_tvOS.entitlements; sourceTree = ""; }; + A361CA3E2C94C17400EB2CA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A361CA662C94D35B00EB2CA3 /* UpVPN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UpVPN.entitlements; sourceTree = ""; }; + A36409E02C9956810077CB46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A364B0B62C7EB9C500A82952 /* UserDataConsent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDataConsent.swift; sourceTree = ""; }; A36565F72C52E5F900C2E748 /* TunnelConfiguration+UapiConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelConfiguration+UapiConfig.swift"; sourceTree = ""; }; A36565FA2C52E87300C2E748 /* String+ArrayConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+ArrayConversion.swift"; sourceTree = ""; }; @@ -353,6 +505,7 @@ A36566502C56E75600C2E748 /* LocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationView.swift; sourceTree = ""; }; A36566532C57031600C2E748 /* Location+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Location+Extension.swift"; sourceTree = ""; }; A365665C2C570B8C00C2E748 /* TunnelStatus+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelStatus+Extension.swift"; sourceTree = ""; }; + A379AAE72C950D1A00BC55AA /* MainContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainContentView.swift; sourceTree = ""; }; A380AA992C6308CF007E09A1 /* PlanRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlanRepository.swift; sourceTree = ""; }; A391D9892C4919FA0008D23F /* UserStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserStore.swift; sourceTree = ""; }; A391D98E2C4939F90008D23F /* StoreError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreError.swift; sourceTree = ""; }; @@ -394,6 +547,15 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + A3212C142C8D69C4005E7D3D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A361CA652C94D0BA00EB2CA3 /* WireGuardKit in Frameworks */, + A38864182C94EBC000E91A1D /* FlagKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; A350DED22C25141100BA1BA6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -430,9 +592,39 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A361CA2C2C94BAA000EB2CA3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A361CA632C94D06200EB2CA3 /* WireGuardKit in Frameworks */, + A361CA302C94BAA000EB2CA3 /* NetworkExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + A3212C182C8D69C4005E7D3D /* tvOS */ = { + isa = PBXGroup; + children = ( + A379AAE62C950CE600BC55AA /* Views */, + A361CA3E2C94C17400EB2CA3 /* Info.plist */, + A3212C1D2C8D69C5005E7D3D /* Assets.xcassets */, + A3212C1F2C8D69C5005E7D3D /* Preview Content */, + A361CA662C94D35B00EB2CA3 /* UpVPN.entitlements */, + A33E307A2C97E4A7001C0E89 /* LaunchScreen.storyboard */, + ); + path = tvOS; + sourceTree = ""; + }; + A3212C1F2C8D69C5005E7D3D /* Preview Content */ = { + isa = PBXGroup; + children = ( + A3212C202C8D69C5005E7D3D /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; A33336C22C479BEF004D8C8E /* Store */ = { isa = PBXGroup; children = ( @@ -445,6 +637,14 @@ path = Store; sourceTree = ""; }; + A33E306E2C971BF8001C0E89 /* Plan */ = { + isa = PBXGroup; + children = ( + A33E306C2C971BE3001C0E89 /* PriceCapsule.swift */, + ); + path = Plan; + sourceTree = ""; + }; A3422DB82C2E3FE600A3D867 /* Model */ = { isa = PBXGroup; children = ( @@ -508,6 +708,7 @@ A3AA4B222C257C75001135FD /* App */, A350DED72C25141200BA1BA6 /* macOS */, A350DEEC2C25147C00BA1BA6 /* iOS */, + A3212C182C8D69C4005E7D3D /* tvOS */, A350DF0E2C251E0C00BA1BA6 /* UpVPNNetworkExtension */, A350DF0B2C251E0B00BA1BA6 /* Frameworks */, A350DED62C25141200BA1BA6 /* Products */, @@ -521,6 +722,8 @@ A350DEEB2C25147C00BA1BA6 /* UpVPN.app */, A350DF0A2C251E0B00BA1BA6 /* UpVPNNetworkExtension.appex */, A350DF1E2C251E2A00BA1BA6 /* UpVPNNetworkExtension.appex */, + A3212C172C8D69C4005E7D3D /* UpVPN.app */, + A361CA2F2C94BAA000EB2CA3 /* UpVPNNetworkExtension.appex */, ); name = Products; sourceTree = ""; @@ -577,10 +780,12 @@ A350DF0E2C251E0C00BA1BA6 /* UpVPNNetworkExtension */ = { isa = PBXGroup; children = ( + A36409E12C99570C0077CB46 /* tvOS */, A350DF0F2C251E0C00BA1BA6 /* PacketTunnelProvider.swift */, A350DF112C251E0C00BA1BA6 /* Info.plist */, A350DF242C251E2A00BA1BA6 /* UpVPNNetworkExtension_macOS.entitlements */, A350DF122C251E0C00BA1BA6 /* UpVPNNetworkExtension_iOS.entitlements */, + A361CA3D2C94BF9B00EB2CA3 /* UpVPNNetworkExtension_tvOS.entitlements */, A3A7636A2C5146C90088D5F5 /* Data */, A3A763692C51460B0088D5F5 /* Orchestrator */, A3A7636B2C5146E40088D5F5 /* Tunnel */, @@ -588,6 +793,14 @@ path = UpVPNNetworkExtension; sourceTree = ""; }; + A36409E12C99570C0077CB46 /* tvOS */ = { + isa = PBXGroup; + children = ( + A36409E02C9956810077CB46 /* Info.plist */, + ); + path = tvOS; + sourceTree = ""; + }; A36565FD2C545F5200C2E748 /* Views */ = { isa = PBXGroup; children = ( @@ -623,6 +836,23 @@ path = Views; sourceTree = ""; }; + A379AAE62C950CE600BC55AA /* Views */ = { + isa = PBXGroup; + children = ( + A33E30762C97D528001C0E89 /* LoginView.swift */, + A33E30742C973FE9001C0E89 /* LocationsView.swift */, + A33E30722C973C88001C0E89 /* HelpView.swift */, + A33E306E2C971BF8001C0E89 /* Plan */, + A33E306A2C96C65D001C0E89 /* StatsCard.swift */, + A33E30682C96B8A4001C0E89 /* VPNSwitch.swift */, + A33E30662C96B201001C0E89 /* HomeCard.swift */, + A33E30622C968EDA001C0E89 /* LocationView.swift */, + A379AAE72C950D1A00BC55AA /* MainContentView.swift */, + A33E30642C969BB7001C0E89 /* HomeView.swift */, + ); + path = Views; + sourceTree = ""; + }; A391D9A52C4978F10008D23F /* Data */ = { isa = PBXGroup; children = ( @@ -721,6 +951,20 @@ /* End PBXGroup section */ /* Begin PBXLegacyTarget section */ + A3212BEB2C8D6450005E7D3D /* WireGuardGoBridgetvOS */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = A3212BEE2C8D6450005E7D3D /* Build configuration list for PBXLegacyTarget "WireGuardGoBridgetvOS" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + buildWorkingDirectory = "$(SOURCE_PACKAGES_DIR)/checkouts/wireguard-apple/Sources/WireGuardKitGo"; + dependencies = ( + ); + name = WireGuardGoBridgetvOS; + passBuildSettingsInEnvironment = 1; + productName = WireGuardGoBridegtvOS; + }; A3AA4B112C256EC2001135FD /* WireGuardGoBridgeiOS */ = { isa = PBXLegacyTarget; buildArgumentsString = "$(ACTION)"; @@ -798,6 +1042,29 @@ /* End PBXLegacyTarget section */ /* Begin PBXNativeTarget section */ + A3212C162C8D69C4005E7D3D /* UpVPNtvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A3212C222C8D69C5005E7D3D /* Build configuration list for PBXNativeTarget "UpVPNtvOS" */; + buildPhases = ( + A3212C132C8D69C4005E7D3D /* Sources */, + A3212C142C8D69C4005E7D3D /* Frameworks */, + A3212C152C8D69C4005E7D3D /* Resources */, + A361CA3C2C94BAA000EB2CA3 /* Embed Foundation Extensions */, + ); + buildRules = ( + ); + dependencies = ( + A361CA372C94BAA000EB2CA3 /* PBXTargetDependency */, + ); + name = UpVPNtvOS; + packageProductDependencies = ( + A361CA642C94D0BA00EB2CA3 /* WireGuardKit */, + A38864172C94EBC000E91A1D /* FlagKit */, + ); + productName = UpVPNtvOS; + productReference = A3212C172C8D69C4005E7D3D /* UpVPN.app */; + productType = "com.apple.product-type.application"; + }; A350DED42C25141100BA1BA6 /* UpVPNmacOS */ = { isa = PBXNativeTarget; buildConfigurationList = A350DEE42C25141300BA1BA6 /* Build configuration list for PBXNativeTarget "UpVPNmacOS" */; @@ -886,6 +1153,27 @@ productReference = A350DF1E2C251E2A00BA1BA6 /* UpVPNNetworkExtension.appex */; productType = "com.apple.product-type.app-extension"; }; + A361CA2E2C94BAA000EB2CA3 /* UpVPNNetworkExtensiontvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A361CA392C94BAA000EB2CA3 /* Build configuration list for PBXNativeTarget "UpVPNNetworkExtensiontvOS" */; + buildPhases = ( + A361CA2B2C94BAA000EB2CA3 /* Sources */, + A361CA2C2C94BAA000EB2CA3 /* Frameworks */, + A361CA2D2C94BAA000EB2CA3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + A361CA412C94CF4D00EB2CA3 /* PBXTargetDependency */, + ); + name = UpVPNNetworkExtensiontvOS; + packageProductDependencies = ( + A361CA622C94D06200EB2CA3 /* WireGuardKit */, + ); + productName = UpVPNNetworkExtensiontvOS; + productReference = A361CA2F2C94BAA000EB2CA3 /* UpVPNNetworkExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -896,6 +1184,12 @@ LastSwiftUpdateCheck = 1540; LastUpgradeCheck = 1540; TargetAttributes = { + A3212BEB2C8D6450005E7D3D = { + CreatedOnToolsVersion = 15.4; + }; + A3212C162C8D69C4005E7D3D = { + CreatedOnToolsVersion = 15.4; + }; A350DED42C25141100BA1BA6 = { CreatedOnToolsVersion = 15.4; }; @@ -908,6 +1202,9 @@ A350DF1D2C251E2A00BA1BA6 = { CreatedOnToolsVersion = 15.4; }; + A361CA2E2C94BAA000EB2CA3 = { + CreatedOnToolsVersion = 15.4; + }; A3AA4B112C256EC2001135FD = { CreatedOnToolsVersion = 15.4; }; @@ -939,11 +1236,25 @@ A350DF1D2C251E2A00BA1BA6 /* UpVPNNetworkExtensionmacOS */, A3AA4B112C256EC2001135FD /* WireGuardGoBridgeiOS */, A3AA4B152C256ED0001135FD /* WireGuardGoBridgemacOS */, + A3212C162C8D69C4005E7D3D /* UpVPNtvOS */, + A361CA2E2C94BAA000EB2CA3 /* UpVPNNetworkExtensiontvOS */, + A3212BEB2C8D6450005E7D3D /* WireGuardGoBridgetvOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + A3212C152C8D69C4005E7D3D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A33E307B2C97E4A7001C0E89 /* LaunchScreen.storyboard in Resources */, + A3212C212C8D69C5005E7D3D /* Preview Assets.xcassets in Resources */, + A33E307D2C9925A4001C0E89 /* PrivacyInfo.xcprivacy in Resources */, + A3212C1E2C8D69C5005E7D3D /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; A350DED32C25141100BA1BA6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -979,9 +1290,91 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A361CA2D2C94BAA000EB2CA3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + A3212C132C8D69C4005E7D3D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A379AAFC2C950F0600BC55AA /* Color+Extension.swift in Sources */, + A361CA7F2C94E8AF00EB2CA3 /* VPNState.swift in Sources */, + A33E30712C972E11001C0E89 /* PrepaidPlansView.swift in Sources */, + A361CA7C2C94E78000EB2CA3 /* AppConfig.swift in Sources */, + A361CA7B2C94E75200EB2CA3 /* StoreKeys.swift in Sources */, + A379AB032C950F3400BC55AA /* KeyValueView.swift in Sources */, + A361CA7A2C94E72D00EB2CA3 /* Utils.swift in Sources */, + A361CA782C94E6C200EB2CA3 /* Keychain.swift in Sources */, + A361CA792C94E6C200EB2CA3 /* Client.swift in Sources */, + A361CA732C94E6A600EB2CA3 /* UserStore.swift in Sources */, + A379AB002C950F2500BC55AA /* AccountView.swift in Sources */, + A379AAF72C950EE600BC55AA /* Location+Extension.swift in Sources */, + A33E30732C973C8A001C0E89 /* HelpView.swift in Sources */, + A361CA742C94E6A600EB2CA3 /* StoreError.swift in Sources */, + A379AAF12C950E6F00BC55AA /* ContentView.swift in Sources */, + A33E30692C96B8AA001C0E89 /* VPNSwitch.swift in Sources */, + A361CA752C94E6A600EB2CA3 /* LocationStore.swift in Sources */, + A379AB092C950F5000BC55AA /* PlanManagement.swift in Sources */, + A361CA762C94E6A600EB2CA3 /* Location.swift in Sources */, + A379AB132C951CBA00BC55AA /* Response.swift in Sources */, + A379AB152C951CC400BC55AA /* NETunnelProviderSessionExtension.swift in Sources */, + A33E306D2C971BE8001C0E89 /* PriceCapsule.swift in Sources */, + A361CA772C94E6A600EB2CA3 /* Types.swift in Sources */, + A33E307C2C992171001C0E89 /* CardContainer.swift in Sources */, + A33E30672C96B210001C0E89 /* HomeCard.swift in Sources */, + A379AAF02C950E4800BC55AA /* LocationsMapView.swift in Sources */, + A361CA6E2C94E62700EB2CA3 /* Device.swift in Sources */, + A33E30632C968EE0001C0E89 /* LocationView.swift in Sources */, + A361CA6F2C94E62700EB2CA3 /* UserCredentials.swift in Sources */, + A379AB142C951CC000BC55AA /* AppMessageHandler.swift in Sources */, + A33E30772C97D52A001C0E89 /* LoginView.swift in Sources */, + A379AAF82C950EEB00BC55AA /* TunnelStatus+Extension.swift in Sources */, + A379AAF42C950EAF00BC55AA /* MainView.swift in Sources */, + A379AB0B2C950F8900BC55AA /* Country.swift in Sources */, + A379AAEA2C950D7400BC55AA /* RuntimeConfigurationView.swift in Sources */, + A379AB012C950F2B00BC55AA /* SignOutView.swift in Sources */, + A361CA702C94E62700EB2CA3 /* VPNApiService.swift in Sources */, + A361CA712C94E62700EB2CA3 /* TunnelManager.swift in Sources */, + A379AAE42C950BFA00BC55AA /* UIUtils.swift in Sources */, + A379AB082C950F4C00BC55AA /* PurchaseButton.swift in Sources */, + A379AAEF2C950E2400BC55AA /* FlagImage.swift in Sources */, + A379AB122C951CB000BC55AA /* Request.swift in Sources */, + A361CA7E2C94E85900EB2CA3 /* TunnelStatus.swift in Sources */, + A379AAE32C9509EF00BC55AA /* FileManager+Extension.swift in Sources */, + A361CA722C94E62700EB2CA3 /* TunnelObserver.swift in Sources */, + A379AB042C950F3B00BC55AA /* UserDataConsent.swift in Sources */, + A379AAEC2C950DB900BC55AA /* SettingsView.swift in Sources */, + A361CA682C94E5E400EB2CA3 /* DeviceStore.swift in Sources */, + A361CA812C94E90300EB2CA3 /* PlanRepository.swift in Sources */, + A361CA7D2C94E84C00EB2CA3 /* TunnelManagerSimulator.swift in Sources */, + A361CA692C94E5E400EB2CA3 /* DataRepository.swift in Sources */, + A379AB0A2C950F5400BC55AA /* PlanView.swift in Sources */, + A361CA6A2C94E5E400EB2CA3 /* TunnelViewModel.swift in Sources */, + A361CA6B2C94E5E400EB2CA3 /* AuthViewModel.swift in Sources */, + A361CA802C94E8E200EB2CA3 /* InterfaceConfiguration+Device.swift in Sources */, + A361CA6C2C94E5E400EB2CA3 /* LocationViewModel.swift in Sources */, + A361CA6D2C94E5E400EB2CA3 /* PlanViewModel.swift in Sources */, + A33E306B2C96C660001C0E89 /* StatsCard.swift in Sources */, + A379AAF92C950EF100BC55AA /* ElapsedTimeView.swift in Sources */, + A379AAF32C950E7D00BC55AA /* WelcomeView.swift in Sources */, + A379AB022C950F3000BC55AA /* VersionView.swift in Sources */, + A33E30652C969BB7001C0E89 /* HomeView.swift in Sources */, + A379AB162C951CE600BC55AA /* TunnelConfiguration+UapiConfig.swift in Sources */, + A379AB0C2C95104100BC55AA /* String+ArrayConversion.swift in Sources */, + A379AB072C950F4800BC55AA /* YearlyPlanView.swift in Sources */, + A33E30752C973FED001C0E89 /* LocationsView.swift in Sources */, + A361CA672C94D68E00EB2CA3 /* UpVPNApp.swift in Sources */, + A379AAE92C950D4B00BC55AA /* MainContentView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; A350DED12C25141100BA1BA6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1215,6 +1608,45 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A361CA2B2C94BAA000EB2CA3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A361CA422C94D04A00EB2CA3 /* VPNState.swift in Sources */, + A361CA432C94D04A00EB2CA3 /* FileManager+Extension.swift in Sources */, + A361CA442C94D04A00EB2CA3 /* Keychain.swift in Sources */, + A361CA452C94D04A00EB2CA3 /* Utils.swift in Sources */, + A361CA462C94D04A00EB2CA3 /* AppConfig.swift in Sources */, + A361CA472C94D04A00EB2CA3 /* DeviceStore.swift in Sources */, + A361CA482C94D04A00EB2CA3 /* StoreKeys.swift in Sources */, + A361CA492C94D04A00EB2CA3 /* UserStore.swift in Sources */, + A361CA4A2C94D04A00EB2CA3 /* StoreError.swift in Sources */, + A361CA4B2C94D04A00EB2CA3 /* LocationStore.swift in Sources */, + A361CA4C2C94D04A00EB2CA3 /* DataRepository.swift in Sources */, + A361CA4D2C94D04A00EB2CA3 /* Request.swift in Sources */, + A361CA4E2C94D04A00EB2CA3 /* Response.swift in Sources */, + A361CA4F2C94D04A00EB2CA3 /* AppMessageHandler.swift in Sources */, + A361CA502C94D04A00EB2CA3 /* Location.swift in Sources */, + A361CA512C94D04A00EB2CA3 /* Device.swift in Sources */, + A361CA522C94D04A00EB2CA3 /* UserCredentials.swift in Sources */, + A361CA532C94D04A00EB2CA3 /* Types.swift in Sources */, + A361CA542C94D04A00EB2CA3 /* InterfaceConfiguration+Device.swift in Sources */, + A361CA552C94D04A00EB2CA3 /* Client.swift in Sources */, + A361CA562C94D04A00EB2CA3 /* VPNApiService.swift in Sources */, + A361CA572C94D04A00EB2CA3 /* PacketTunnelProvider.swift in Sources */, + A361CA582C94D04A00EB2CA3 /* VPNSessionWatcher.swift in Sources */, + A361CA592C94D04A00EB2CA3 /* VPNSessionRepository.swift in Sources */, + A361CA5A2C94D04A00EB2CA3 /* VPNSessionStore.swift in Sources */, + A361CA5B2C94D04A00EB2CA3 /* VPNSessionReclaimer.swift in Sources */, + A361CA5C2C94D04A00EB2CA3 /* OrcestratorCommand.swift in Sources */, + A361CA5D2C94D04A00EB2CA3 /* VPNOrchestrator.swift in Sources */, + A361CA5E2C94D04A00EB2CA3 /* VPNOrchestratorState.swift in Sources */, + A361CA5F2C94D04A00EB2CA3 /* ErrorNotifier.swift in Sources */, + A361CA602C94D04A00EB2CA3 /* TunnelConfigurationExtension.swift in Sources */, + A361CA612C94D04A00EB2CA3 /* WGAdapterAsync.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -1228,6 +1660,16 @@ target = A350DF1D2C251E2A00BA1BA6 /* UpVPNNetworkExtensionmacOS */; targetProxy = A350DF252C251E2A00BA1BA6 /* PBXContainerItemProxy */; }; + A361CA372C94BAA000EB2CA3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A361CA2E2C94BAA000EB2CA3 /* UpVPNNetworkExtensiontvOS */; + targetProxy = A361CA362C94BAA000EB2CA3 /* PBXContainerItemProxy */; + }; + A361CA412C94CF4D00EB2CA3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A3212BEB2C8D6450005E7D3D /* WireGuardGoBridgetvOS */; + targetProxy = A361CA402C94CF4D00EB2CA3 /* PBXContainerItemProxy */; + }; A3AA4B1A2C256F69001135FD /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = A3AA4B112C256EC2001135FD /* WireGuardGoBridgeiOS */; @@ -1241,6 +1683,104 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + A3212BEC2C8D6450005E7D3D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEBUGGING_SYMBOLS = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GOOS_appletvos = ios; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PATH = "$PATH:/opt/homebrew/bin"; + PLATFORM_NAME = appletvos; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + }; + name = Debug; + }; + A3212BED2C8D6450005E7D3D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GOOS_appletvos = ios; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PATH = "$PATH:/opt/homebrew/bin"; + PLATFORM_NAME = appletvos; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + }; + name = Release; + }; + A3212C232C8D69C5005E7D3D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = tvOS/UpVPN.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "tvOS/Preview\\ Content"; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = tvOS/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = UpVPN; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UIUserInterfaceStyle = Automatic; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_TVOS)"; + PRODUCT_NAME = UpVPN; + SDKROOT = appletvos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 18.0; + }; + name = Debug; + }; + A3212C242C8D69C5005E7D3D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = tvOS/UpVPN.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "tvOS/Preview\\ Content"; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = tvOS/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = UpVPN; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UIUserInterfaceStyle = Automatic; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_TVOS)"; + PRODUCT_NAME = UpVPN; + SDKROOT = appletvos; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 18.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; A350DEE22C25141300BA1BA6 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A33336B22C457D84004D8C8E /* Config.xcconfig */; @@ -1623,6 +2163,61 @@ }; name = Release; }; + A361CA3A2C94BAA000EB2CA3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = UpVPNNetworkExtension/UpVPNNetworkExtension_tvOS.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = UpVPNNetworkExtension/tvOS/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = UpVPNNetworkExtensiontvOS; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_TVOS).network-extension"; + PRODUCT_NAME = UpVPNNetworkExtension; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 18.0; + }; + name = Debug; + }; + A361CA3B2C94BAA000EB2CA3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = UpVPNNetworkExtension/UpVPNNetworkExtension_tvOS.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = UpVPNNetworkExtension/tvOS/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = UpVPNNetworkExtensiontvOS; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_TVOS).network-extension"; + PRODUCT_NAME = UpVPNNetworkExtension; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 18.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; A3AA4B132C256EC2001135FD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1690,6 +2285,24 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + A3212BEE2C8D6450005E7D3D /* Build configuration list for PBXLegacyTarget "WireGuardGoBridgetvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A3212BEC2C8D6450005E7D3D /* Debug */, + A3212BED2C8D6450005E7D3D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A3212C222C8D69C5005E7D3D /* Build configuration list for PBXNativeTarget "UpVPNtvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A3212C232C8D69C5005E7D3D /* Debug */, + A3212C242C8D69C5005E7D3D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; A350DED02C25141100BA1BA6 /* Build configuration list for PBXProject "UpVPN" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1735,6 +2348,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + A361CA392C94BAA000EB2CA3 /* Build configuration list for PBXNativeTarget "UpVPNNetworkExtensiontvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A361CA3A2C94BAA000EB2CA3 /* Debug */, + A361CA3B2C94BAA000EB2CA3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; A3AA4B122C256EC2001135FD /* Build configuration list for PBXLegacyTarget "WireGuardGoBridgeiOS" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1769,7 +2391,7 @@ repositoryURL = "https://github.com/upvpn/wireguard-apple"; requirement = { kind = revision; - revision = b40a6251d29b944932c31a0696a94ceb4a00a005; + revision = d6ca70c60dd92eb5c997f2092ef71577ef07040b; }; }; /* End XCRemoteSwiftPackageReference section */ @@ -1785,6 +2407,16 @@ package = A3AA4B0C2C256CFD001135FD /* XCRemoteSwiftPackageReference "wireguard-apple" */; productName = WireGuardKit; }; + A361CA622C94D06200EB2CA3 /* WireGuardKit */ = { + isa = XCSwiftPackageProductDependency; + package = A3AA4B0C2C256CFD001135FD /* XCRemoteSwiftPackageReference "wireguard-apple" */; + productName = WireGuardKit; + }; + A361CA642C94D0BA00EB2CA3 /* WireGuardKit */ = { + isa = XCSwiftPackageProductDependency; + package = A3AA4B0C2C256CFD001135FD /* XCRemoteSwiftPackageReference "wireguard-apple" */; + productName = WireGuardKit; + }; A36566582C57071A00C2E748 /* FlagKit */ = { isa = XCSwiftPackageProductDependency; package = A36566572C57070C00C2E748 /* XCRemoteSwiftPackageReference "FlagKit" */; @@ -1795,6 +2427,11 @@ package = A36566572C57070C00C2E748 /* XCRemoteSwiftPackageReference "FlagKit" */; productName = FlagKit; }; + A38864172C94EBC000E91A1D /* FlagKit */ = { + isa = XCSwiftPackageProductDependency; + package = A36566572C57070C00C2E748 /* XCRemoteSwiftPackageReference "FlagKit" */; + productName = FlagKit; + }; A3AA4B1B2C256F72001135FD /* WireGuardKit */ = { isa = XCSwiftPackageProductDependency; package = A3AA4B0C2C256CFD001135FD /* XCRemoteSwiftPackageReference "wireguard-apple" */; diff --git a/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7b54aac..90735e4 100644 --- a/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/upvpn-apple/UpVPN/UpVPN.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "bd0020a40e930c31183511f81e0427b203d42212c20477ff8b1cafc3e995cbe4", + "originHash" : "cec72ce8a25e7626c8eb7b18c5aa4242ac51ee109d1016c39a18faf14f64a21f", "pins" : [ { "identity" : "flagkit", @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/upvpn/wireguard-apple", "state" : { - "revision" : "b40a6251d29b944932c31a0696a94ceb4a00a005" + "revision" : "d6ca70c60dd92eb5c997f2092ef71577ef07040b" } } ], diff --git a/upvpn-apple/UpVPN/UpVPN.xcodeproj/xcshareddata/xcschemes/UpVPNNetworkExtensiontvOS.xcscheme b/upvpn-apple/UpVPN/UpVPN.xcodeproj/xcshareddata/xcschemes/UpVPNNetworkExtensiontvOS.xcscheme new file mode 100644 index 0000000..0cbe998 --- /dev/null +++ b/upvpn-apple/UpVPN/UpVPN.xcodeproj/xcshareddata/xcschemes/UpVPNNetworkExtensiontvOS.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/upvpn-apple/UpVPN/UpVPN.xcodeproj/xcshareddata/xcschemes/UpVPNtvOS.xcscheme b/upvpn-apple/UpVPN/UpVPN.xcodeproj/xcshareddata/xcschemes/UpVPNtvOS.xcscheme new file mode 100644 index 0000000..b2231d5 --- /dev/null +++ b/upvpn-apple/UpVPN/UpVPN.xcodeproj/xcshareddata/xcschemes/UpVPNtvOS.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/upvpn-apple/UpVPN/UpVPNNetworkExtension/Info.plist b/upvpn-apple/UpVPN/UpVPNNetworkExtension/Info.plist index b40152b..6e5af85 100644 --- a/upvpn-apple/UpVPN/UpVPNNetworkExtension/Info.plist +++ b/upvpn-apple/UpVPN/UpVPNNetworkExtension/Info.plist @@ -28,6 +28,8 @@ $(DEVELOPMENT_TEAM).group.$(APP_ID_MACOS) app.upvpn.apple.ios.app_group_id group.$(APP_ID_IOS) + app.upvpn.apple.tvos.app_group_id + group.$(APP_ID_TVOS) app.upvpn.apple.macos.keychain_group_id $(DEVELOPMENT_TEAM).$(APP_ID_MACOS).keychain NSExtension diff --git a/upvpn-apple/UpVPN/UpVPNNetworkExtension/UpVPNNetworkExtension_tvOS.entitlements b/upvpn-apple/UpVPN/UpVPNNetworkExtension/UpVPNNetworkExtension_tvOS.entitlements new file mode 100644 index 0000000..7faf5ba --- /dev/null +++ b/upvpn-apple/UpVPN/UpVPNNetworkExtension/UpVPNNetworkExtension_tvOS.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.application-groups + + group.$(APP_ID_TVOS) + + + diff --git a/upvpn-apple/UpVPN/UpVPNNetworkExtension/tvOS/Info.plist b/upvpn-apple/UpVPN/UpVPNNetworkExtension/tvOS/Info.plist new file mode 100644 index 0000000..210de14 --- /dev/null +++ b/upvpn-apple/UpVPN/UpVPNNetworkExtension/tvOS/Info.plist @@ -0,0 +1,39 @@ + + + + + ITSAppUsesNonExemptEncryption + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + UpVPNNetworkExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + $(VERSION_NAME) + CFBundleVersion + $(VERSION_ID) + app.upvpn.apple.tvos.app_group_id + group.$(APP_ID_TVOS) + UIRequiredDeviceCapabilities + + arm64 + + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + + diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/AccentColor.colorset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..f9a2661 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "iconTVOSBack.png", + "idiom" : "tv" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/iconTVOSBack.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/iconTVOSBack.png new file mode 100644 index 0000000..fc14ea5 Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/iconTVOSBack.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..de59d88 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ] +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..a0058ca --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "iconTVOSFront.png", + "idiom" : "tv" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/iconTVOSFront.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/iconTVOSFront.png new file mode 100644 index 0000000..b250737 Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/iconTVOSFront.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..2e00335 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..8f35264 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "filename" : "back_400x240@1x.png", + "idiom" : "tv", + "scale" : "1x" + }, + { + "filename" : "back_800x480@2x.png", + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back_400x240@1x.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back_400x240@1x.png new file mode 100644 index 0000000..7389309 Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back_400x240@1x.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back_800x480@2x.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back_800x480@2x.png new file mode 100644 index 0000000..d9ee69e Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/back_800x480@2x.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..de59d88 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ] +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..c1eb194 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "filename" : "front_400x240@1x.png", + "idiom" : "tv", + "scale" : "1x" + }, + { + "filename" : "front_800x480@2x.png", + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front_400x240@1x.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front_400x240@1x.png new file mode 100644 index 0000000..59c2980 Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front_400x240@1x.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front_800x480@2x.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front_800x480@2x.png new file mode 100644 index 0000000..6887c5e Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/front_800x480@2x.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..795cce1 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json new file mode 100644 index 0000000..f47ba43 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -0,0 +1,32 @@ +{ + "assets" : [ + { + "filename" : "App Icon - App Store.imagestack", + "idiom" : "tv", + "role" : "primary-app-icon", + "size" : "1280x768" + }, + { + "filename" : "App Icon.imagestack", + "idiom" : "tv", + "role" : "primary-app-icon", + "size" : "400x240" + }, + { + "filename" : "Top Shelf Image Wide.imageset", + "idiom" : "tv", + "role" : "top-shelf-image-wide", + "size" : "2320x720" + }, + { + "filename" : "Top Shelf Image.imageset", + "idiom" : "tv", + "role" : "top-shelf-image", + "size" : "1920x720" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..bc09af9 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "filename" : "top_shelf2320x720.png", + "idiom" : "tv", + "scale" : "1x" + }, + { + "filename" : "UpVPN.png", + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/UpVPN.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/UpVPN.png new file mode 100644 index 0000000..928638b Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/UpVPN.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top_shelf2320x720.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top_shelf2320x720.png new file mode 100644 index 0000000..8000aed Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top_shelf2320x720.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..795cce1 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/Contents.json b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/Contents.json new file mode 100644 index 0000000..643c555 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icon_128x128.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_128x128@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_128x128@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128.png new file mode 100644 index 0000000..a6edc35 Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128@2x.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128@2x.png new file mode 100644 index 0000000..b602a8e Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128@2x.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128@3x.png b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128@3x.png new file mode 100644 index 0000000..d929e32 Binary files /dev/null and b/upvpn-apple/UpVPN/tvOS/Assets.xcassets/upvpn.imageset/icon_128x128@3x.png differ diff --git a/upvpn-apple/UpVPN/tvOS/Info.plist b/upvpn-apple/UpVPN/tvOS/Info.plist new file mode 100644 index 0000000..73916bf --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + $(PRODUCT_NAME) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(VERSION_NAME) + CFBundleVersion + $(VERSION_ID) + ITSAppUsesNonExemptEncryption + + UILaunchStoryboardName + LaunchScreen + app.upvpn.apple.tvos.app_group_id + group.$(APP_ID_TVOS) + + diff --git a/upvpn-apple/UpVPN/tvOS/LaunchScreen.storyboard b/upvpn-apple/UpVPN/tvOS/LaunchScreen.storyboard new file mode 100644 index 0000000..9f37a45 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/LaunchScreen.storyboard @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/upvpn-apple/UpVPN/tvOS/Preview Content/Preview Assets.xcassets/Contents.json b/upvpn-apple/UpVPN/tvOS/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/upvpn-apple/UpVPN/tvOS/UpVPN.entitlements b/upvpn-apple/UpVPN/tvOS/UpVPN.entitlements new file mode 100644 index 0000000..7faf5ba --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/UpVPN.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.application-groups + + group.$(APP_ID_TVOS) + + + diff --git a/upvpn-apple/UpVPN/tvOS/Views/HelpView.swift b/upvpn-apple/UpVPN/tvOS/Views/HelpView.swift new file mode 100644 index 0000000..10f7e09 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/HelpView.swift @@ -0,0 +1,38 @@ +// +// HelpView.swift +// UpVPN +// +// Created by Himanshu on 9/15/24. +// + +import SwiftUI + +struct HelpView: View { + var body: some View { + Group { + VStack { + Text(""" +Have questions about **product** or **pricing**? + +Visit FAQ at https://upvpn.app/faq/ + +Or send us a message at **support@upvpn.app** and we'll be happy to assist! +""") + + Spacer() + Text(""" +Acknowledgements: https://upvpn.app/oss/apple/ +""").font(.caption).padding() + + } + } + .padding() + .multilineTextAlignment(.leading) + .navigationTitle("Help") + .frame(maxWidth: .infinity) + } +} + +#Preview { + HelpView() +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/HomeCard.swift b/upvpn-apple/UpVPN/tvOS/Views/HomeCard.swift new file mode 100644 index 0000000..2d913a7 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/HomeCard.swift @@ -0,0 +1,79 @@ +// +// HomeCard.swift +// UpVPN +// +// Created by Himanshu on 9/14/24. +// + +import SwiftUI + +struct HomeCard: View { + @EnvironmentObject private var tunnelViewModel: TunnelViewModel + + var body: some View { + VStack(alignment: .leading) { + Spacer() + + HStack { + HStack(spacing: 15) { + + Image(systemName: tunnelViewModel.tunnelObserver.tunnelStatus.shieldSystemImage()) + .resizable() + .scaledToFit() + .frame(minWidth: 50, maxWidth: 100, minHeight: 50, maxHeight: 100) + .font(.headline.weight(.light)) + + if case .connected(_, let date) = tunnelViewModel.tunnelObserver.tunnelStatus { + ElapsedTimeView(startDate: date) + .background( + Capsule() + .fill(.ultraThinMaterial) + .stroke(.white) + ) + } else { + Text(tunnelViewModel.tunnelObserver.tunnelStatus.displayText()) + .font(.headline) + .padding(.bottom, 2).padding(.top, 2) + .padding(.trailing, 10) + .padding(.leading, 10) + .background( + Capsule() + .fill(.ultraThinMaterial) + .stroke(.white) + ) + } + } + .padding() + + Spacer() + if tunnelViewModel.tunnelObserver.tunnelStatus.isConnected(), + let runtimeConfig = tunnelViewModel.tunnelObserver.runtimeConfig, + let peer = runtimeConfig.peers.first, + let tx = peer.txBytes, + let rx = peer.rxBytes + + { + + StatsCard(tx: prettyBytes(tx), rx: prettyBytes(rx)) + .frame(maxHeight: .infinity) + .scaledToFit() + .padding() + .background(.ultraThinMaterial) + .clipShape(RoundedRectangle(cornerRadius: 15)) + .padding(.trailing, 10) + + } + } + .padding(.horizontal) + + Spacer() + + + } + .padding(.vertical, 10) + .background(Color.clear) + .clipShape(RoundedRectangle(cornerRadius: 10)) + .frame( maxWidth: .infinity) + } +} + diff --git a/upvpn-apple/UpVPN/tvOS/Views/HomeView.swift b/upvpn-apple/UpVPN/tvOS/Views/HomeView.swift new file mode 100644 index 0000000..36340a3 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/HomeView.swift @@ -0,0 +1,110 @@ +// +// HomeView.swift +// UpVPNtvOS +// +// Created by Himanshu on 9/14/24. +// + +import SwiftUI + +private func showProgressView(_ tunnelStatus: TunnelStatus) -> Bool { + switch tunnelStatus { + case .requesting, .accepted, .serverCreated, .serverRunning, .serverReady, .connecting: + return true + default: + return false + } +} + +struct HomeView: View { + @EnvironmentObject private var tunnelViewModel: TunnelViewModel + @EnvironmentObject private var authViewModel: AuthViewModel + @EnvironmentObject private var locationViewModel: LocationViewModel + + var body: some View { + ScrollView(.vertical) { + VStack(alignment: .leading) { + // header + ZStack { + LocationsMapView(coordinateSpan: .large) + .focusable(false) + .clipShape(RoundedRectangle(cornerRadius: 20)) + + VStack { + HomeCard() + } + + if showProgressView(tunnelViewModel.tunnelObserver.tunnelStatus) { + VStack { + Spacer() + ProgressView(value: tunnelViewModel.tunnelObserver.tunnelStatus.progress()) + .tint(.blue) + .padding(.horizontal, 30) + .padding(.bottom, 30) + } + } + } + .frame(maxWidth: .infinity, alignment: .leading) + .containerRelativeFrame(.vertical, alignment: .topLeading) { + length, _ in length * 0.5 + } + .focusable(false) + + VPNSwitch(tunnelStatus: tunnelViewModel.tunnelObserver.tunnelStatus, + start: { + if let location = locationViewModel.selected { + locationViewModel.addRecent(location: location) + tunnelViewModel.start(to: location) + } + }, + stop: { + tunnelViewModel.stop() + }) + .scrollClipDisabled() + .padding(.bottom, 25) + + if !locationViewModel.recentLocations.isEmpty { + Section("Recent Locations") { + ScrollView(.horizontal) { + LazyHStack(spacing: 30) { + ForEach(locationViewModel.recentLocations.reversed()) { location in + LocationView(location: location) + .padding(.top, 10) + .padding(.bottom, 45) + } + } + .id(locationViewModel.locationsLastUpdated) + } + } + } + + ForEach(Location.countries(from: locationViewModel.locations)) { country in + Section(country.name) { + ScrollView(.horizontal) { + LazyHStack(spacing: 30) { + ForEach(country.locations) { location in + LocationView(location: location) + .padding(.top, 10) + .padding(.bottom, 45) + } + } + .id(locationViewModel.locationsLastUpdated) + } + } + } + + } + .scrollTargetLayout() + } + .scrollClipDisabled() + } +} + +#Preview { + let locationViewModel = LocationViewModel(dataRepository: DataRepository.shared, isDisconnected: {return true}) + //locationViewModel.recentLocations = [Location.default, Location.testLocation] + return HomeView() + .environmentObject(TunnelViewModel()) + .environmentObject(AuthViewModel(dataRepository: DataRepository.shared, isDisconnected: {return true})) + .environmentObject(locationViewModel) +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/LocationView.swift b/upvpn-apple/UpVPN/tvOS/Views/LocationView.swift new file mode 100644 index 0000000..73af65e --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/LocationView.swift @@ -0,0 +1,48 @@ +// +// LocationView.swift +// UpVPN +// +// Created by Himanshu on 9/14/24. +// + +import SwiftUI +import FlagKit + +struct LocationView: View { + var location: Location + + @EnvironmentObject var locationViewModel: LocationViewModel + + var body: some View { + Button { + withAnimation { + locationViewModel.setSelected(location: location) + } + } label: { + HStack(spacing: 15) { + FlagImage(countryCode: location.countryCode) + .frame(maxHeight: .infinity) + Text(location.displayText()) + .font(.headline) + .fixedSize() + Spacer() + HStack(spacing: 20) { + if (location.code == locationViewModel.selected?.code) { + Image(systemName: "checkmark.circle").foregroundColor(Color.green) + } + + Circle() + .fill(location.warmOrColdColor()) + .frame(width: 24, height: 24) + } + } + .padding() + .cornerRadius(15) + } + } +} + +#Preview { + LocationView(location: Location.testLocation) + .environmentObject(LocationViewModel(dataRepository: DataRepository.shared, isDisconnected: { return true })) +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/LocationsView.swift b/upvpn-apple/UpVPN/tvOS/Views/LocationsView.swift new file mode 100644 index 0000000..ee70826 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/LocationsView.swift @@ -0,0 +1,55 @@ +// +// LocationsView.swift +// UpVPN +// +// Created by Himanshu on 9/15/24. +// + +import SwiftUI + +struct LocationsView: View { + + @EnvironmentObject private var locationViewModel: LocationViewModel + + @State private var search: String = "" + + private let columns: [GridItem] = Array(repeating: .init(.flexible(), spacing: 55), count: 3) + + private var filteredLocations: [Location] { + var computedLocations = if search.isEmpty { + locationViewModel.locations + } else { + locationViewModel.locations.filter { location in location.matches(query: search) } + } + + computedLocations.sort { $0.city < $1.city } + + return computedLocations + } + + var body: some View { + ScrollView(.vertical) { + LazyVGrid(columns: columns, spacing: 55) { + ForEach(filteredLocations) { location in + LocationView(location: location) + .tag(location) + } + } + .id(locationViewModel.locationsLastUpdated) + + } + .scrollClipDisabled() + .searchable(text: $search, placement: .automatic) + .refreshable { + locationViewModel.reload() + } + .onAppear { + locationViewModel.reload() + } + } +} + +#Preview { + LocationsView() + .environmentObject(LocationViewModel(dataRepository: DataRepository.shared, isDisconnected: { return true })) +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/LoginView.swift b/upvpn-apple/UpVPN/tvOS/Views/LoginView.swift new file mode 100644 index 0000000..780b00f --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/LoginView.swift @@ -0,0 +1,145 @@ +// +// LoginView.swift +// UpVPN +// +// Created by Himanshu on 9/15/24. +// + +import SwiftUI + +struct PasswordField: View { + @Binding var password: String + @State private var showPassword: Bool = false + + var body: some View { + HStack(spacing: 20) { + if showPassword { + TextField("Password", text: $password) + } else { + SecureField("Password", text: $password) + } + + Button(action: { + showPassword.toggle() + }) { + Image(systemName: showPassword ? "eye" : "eye.slash") + .foregroundColor(.gray) + } + } + .padding(12) + .textFieldStyle(PlainTextFieldStyle()) + .keyboardType(.default) + } +} + +struct LoginView: View { + @EnvironmentObject private var authViewModel: AuthViewModel + + @State private var isSignInErrorPresented = false + + @AppStorage("userConsent") private var userConsent: Bool = false + + @State private var dataForUserConsentIsPresented = false + + var body: some View { + VStack(spacing: 35) { + + VStack(spacing: 5) { + WelcomeView(showSpinnner: false) + Text("UpVPN") + .font(.largeTitle.bold()) + + Text("A Modern Serverless VPN") + .font(.headline.weight(.thin)) + } + + + VStack(spacing: 20) { + TextField("Email", text: $authViewModel.userCredentials.email) + .padding(12) + .textFieldStyle(PlainTextFieldStyle()) + .keyboardType(.emailAddress) + + + PasswordField(password: $authViewModel.userCredentials.password) + + + HStack(spacing: 20) { + Button { dataForUserConsentIsPresented.toggle() } label: { + Text("Associate device data to your account") + } + + Toggle("Agree", isOn: $userConsent) + } + + Button { + if userConsent { + authViewModel.signIn() + } + } label: { + if authViewModel.signInState == .signingIn { + ProgressView() + .padding(.vertical, 5) + .frame(maxWidth: .infinity) + } else { + Text("Sign In") + .padding(.vertical, 5) + .frame(maxWidth: .infinity) + } + } + .buttonStyle(.borderedProminent) + .disabled(!userConsent) + + } + .disabled(authViewModel.signInState == .signingIn) + + + HStack { + Text(""" +By using UpVPN.app you agree to our [Terms](https://upvpn.app/terms-of-service) and [Privacy Policy](https://upvpn.app/privacy-policy) +""") + } + .font(.caption) + .multilineTextAlignment(.leading) + + } + .padding() + .frame(minWidth: 400, maxWidth: .infinity) + .onReceive(authViewModel.$userCredentials) { _ in + authViewModel.clearSignInError() + } + .onReceive(authViewModel.$signInErrorMessage) { error in + if let error = error { + if !error.isEmpty { + isSignInErrorPresented = true + } + } + } + .onSubmit { + if userConsent { + authViewModel.signIn() + } + } + .alert( + "Sign In", + isPresented: $isSignInErrorPresented, + presenting: authViewModel.signInErrorMessage + ) { _ in + Button(role: .cancel) { + authViewModel.clearSignInError() + } label: { + Text("OK") + } + } message: { error in + Text(error) + } + .sheet(isPresented: $dataForUserConsentIsPresented) { + UserDataConsent() + } + } +} + +#Preview { + LoginView() + .environmentObject(AuthViewModel(dataRepository: DataRepository.shared, isDisconnected: { return true })) +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/MainContentView.swift b/upvpn-apple/UpVPN/tvOS/Views/MainContentView.swift new file mode 100644 index 0000000..e4dec3e --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/MainContentView.swift @@ -0,0 +1,45 @@ +// +// MainContentView.swift +// UpVPNmacOS +// +// Created by Himanshu on 9/13/24. +// + + +import SwiftUI + +struct MainViewContent : View { + + @EnvironmentObject var tunnelViewModel: TunnelViewModel + + var body: some View { + NavigationStack { + TabView() { + Tab("Home", systemImage: "house") { + HomeView() + } + + Tab("Locations", systemImage: "location") { + LocationsView() + } + + Tab("Config", systemImage: "network") { + RuntimeConfigurationView() + } + + Tab("Account", systemImage: "person") { + SettingsView() + } + } + } + } +} + +#Preview { + let locationViewModel = LocationViewModel(dataRepository: DataRepository.shared, isDisconnected: {return true}) + + return MainViewContent() + .environmentObject(TunnelViewModel()) + .environmentObject(AuthViewModel(dataRepository: DataRepository.shared, isDisconnected: {return true})) + .environmentObject(locationViewModel) +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/Plan/PriceCapsule.swift b/upvpn-apple/UpVPN/tvOS/Views/Plan/PriceCapsule.swift new file mode 100644 index 0000000..2396e35 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/Plan/PriceCapsule.swift @@ -0,0 +1,37 @@ +// +// PriceCapsule.swift +// UpVPN +// +// Created by Himanshu on 9/15/24. +// + +import SwiftUI + +struct PriceCapsule: View { + let text: String + let isSelected: Bool + + @FocusState private var isFocused: Bool + + var body: some View { + HStack(alignment: .center) { + Text(text) + .font(.headline) + .scaledToFit() + .padding(.horizontal, 20) + .padding(.vertical, 10) + .frame(maxWidth: .infinity) + .background( + RoundedRectangle(cornerRadius: 15) + .fill(isFocused ? Color.white : Color.blue.opacity(0.1)) + .overlay( + RoundedRectangle(cornerRadius: 15) + .stroke(isSelected ? Color.blue : Color.clear, lineWidth: 2) + ) + ) + .foregroundColor(.blue) + } + .focusable() + .focused($isFocused) + } +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/StatsCard.swift b/upvpn-apple/UpVPN/tvOS/Views/StatsCard.swift new file mode 100644 index 0000000..c5e92de --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/StatsCard.swift @@ -0,0 +1,51 @@ +// +// StatsCard.swift +// UpVPN +// +// Created by Himanshu on 9/15/24. +// + +import SwiftUI + +struct StatsCard: View { + + var tx: String + var rx: String + + var body: some View { + VStack() { + Stat(systemName: "arrow.down.circle", text: rx, caption: "DOWNLOADED") + Divider() + .padding() + Stat(systemName: "arrow.up.circle", text: tx, caption: "UPLOADED") + } + } +} + +struct Stat: View { + var systemName: String + var text: String + var caption: String + + var body: some View { + HStack(spacing: 10) { + Image(systemName: systemName) + .resizable() + .scaledToFit() + .frame(width: 40, height: 40) + + VStack(alignment: .leading, spacing: 5) { + Text(text) + .font(.headline) + Text(caption) + .font(.caption) + .fontWeight(.regular) + .opacity(0.5) + } + } + } +} + +#Preview { + StatsCard(tx: "10 KiB", rx: "100 GiB") +} diff --git a/upvpn-apple/UpVPN/tvOS/Views/VPNSwitch.swift b/upvpn-apple/UpVPN/tvOS/Views/VPNSwitch.swift new file mode 100644 index 0000000..4967cb9 --- /dev/null +++ b/upvpn-apple/UpVPN/tvOS/Views/VPNSwitch.swift @@ -0,0 +1,45 @@ +// +// VPNSwitch.swift +// UpVPN +// +// Created by Himanshu on 9/14/24. +// + +import SwiftUI + +struct VPNSwitch: View { + var tunnelStatus: TunnelStatus + var start: () -> Void = {} + var stop: () -> Void = {} + + private var isOnBinding: Binding { + Binding( + get: { self.tunnelStatus.shouldToggleBeOn() }, + set: { newValue in + if newValue != self.tunnelStatus.shouldToggleBeOn() { + if newValue { + self.start() + } else { + self.stop() + } + } + } + ) + } + + + var body: some View { + Toggle(isOn: isOnBinding) { + HStack(spacing: 15) { + Text(self.tunnelStatus.displayText()) + if !self.tunnelStatus.isDisconnectedOrConnected() { + ProgressView() + } + } + } + .disabled(!tunnelStatus.isDisconnectedOrConnected()) + .background(Color.clear) + .clipShape(RoundedRectangle(cornerRadius: 10)) + .frame( maxWidth: .infinity) + } +} diff --git a/upvpn-assets/tvos/create_iconset.sh b/upvpn-assets/tvos/create_iconset.sh new file mode 100755 index 0000000..77f5876 --- /dev/null +++ b/upvpn-assets/tvos/create_iconset.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +if [ $# -eq 0 ]; then + echo "Please provide the path to your 1280x768 icon." + exit 1 +fi + +input_icon="$1" +name=${2:-"iconTVOS"} + + +sips -z 240 400 "$input_icon" --out "${name}_400x240@1x.png" +sips -z 480 800 "$input_icon" --out "${name}_800x480@2x.png" + + +echo "Icons created successfully." diff --git a/upvpn-assets/tvos/create_topshelf.sh b/upvpn-assets/tvos/create_topshelf.sh new file mode 100755 index 0000000..286032e --- /dev/null +++ b/upvpn-assets/tvos/create_topshelf.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +if [ $# -eq 0 ]; then + echo "Please provide the path to your 4640x1440 image" + exit 1 +fi + +input_icon="$1" + + +sips -z 720 2320 "$input_icon" --out "top_shelf2320x720.png" + + +echo "created successfully." diff --git a/upvpn-assets/tvos/front_400x240@1x.png b/upvpn-assets/tvos/front_400x240@1x.png new file mode 100644 index 0000000..59c2980 Binary files /dev/null and b/upvpn-assets/tvos/front_400x240@1x.png differ diff --git a/upvpn-assets/tvos/front_800x480@2x.png b/upvpn-assets/tvos/front_800x480@2x.png new file mode 100644 index 0000000..6887c5e Binary files /dev/null and b/upvpn-assets/tvos/front_800x480@2x.png differ diff --git a/upvpn-assets/tvos/iconTVOS.png b/upvpn-assets/tvos/iconTVOS.png new file mode 100644 index 0000000..b1eb60e Binary files /dev/null and b/upvpn-assets/tvos/iconTVOS.png differ diff --git a/upvpn-assets/tvos/iconTVOS.xcf b/upvpn-assets/tvos/iconTVOS.xcf new file mode 100644 index 0000000..0daea44 Binary files /dev/null and b/upvpn-assets/tvos/iconTVOS.xcf differ diff --git a/upvpn-assets/tvos/iconTVOSBack.png b/upvpn-assets/tvos/iconTVOSBack.png new file mode 100644 index 0000000..fc14ea5 Binary files /dev/null and b/upvpn-assets/tvos/iconTVOSBack.png differ diff --git a/upvpn-assets/tvos/iconTVOSFront.png b/upvpn-assets/tvos/iconTVOSFront.png new file mode 100644 index 0000000..b250737 Binary files /dev/null and b/upvpn-assets/tvos/iconTVOSFront.png differ diff --git a/upvpn-assets/tvos/top_shelf2320x720.png b/upvpn-assets/tvos/top_shelf2320x720.png new file mode 100644 index 0000000..8000aed Binary files /dev/null and b/upvpn-assets/tvos/top_shelf2320x720.png differ diff --git a/upvpn-assets/tvos/tvos-top-shelf.png b/upvpn-assets/tvos/tvos-top-shelf.png new file mode 100644 index 0000000..928638b Binary files /dev/null and b/upvpn-assets/tvos/tvos-top-shelf.png differ