mirror of
https://github.com/jkcoxson/LocalDevVPN.git
synced 2026-03-02 06:26:16 +01:00
add Setup
This commit is contained in:
Binary file not shown.
@@ -3,4 +3,52 @@
|
||||
uuid = "E9FBFA8B-D737-454C-9876-DFFB697E8C2D"
|
||||
type = "1"
|
||||
version = "2.0">
|
||||
<Breakpoints>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "EBA30226-5BCA-4729-8062-C41AF6A700D2"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "StosVPN/ContentView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "612"
|
||||
endingLineNumber = "612"
|
||||
landmarkName = "body"
|
||||
landmarkType = "24">
|
||||
<Locations>
|
||||
<Location
|
||||
uuid = "EBA30226-5BCA-4729-8062-C41AF6A700D2 - 41082001a4351f4b"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
symbolName = "closure #3 () -> SwiftUI.TupleView<(SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, SwiftUI.Text)>>, SwiftUI.Button<SwiftUI.Text>, SwiftUI.NavigationLink<SwiftUI.Text, StosVPN.HelpView>)> in closure #1 () -> SwiftUI.TupleView<(SwiftUI.Section<SwiftUI.Text, SwiftUI.TupleView<(SwiftUI.Toggle<SwiftUI.Text>, SwiftUI.NavigationLink<SwiftUI.Label<SwiftUI.Text, SwiftUI.Image>, StosVPN.ConnectionLogView>)>, SwiftUI.EmptyView>, SwiftUI.Section<SwiftUI.Text, SwiftUI.TupleView<(SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, <<opaque return type of SwiftUI.View.keyboardType(__C.UIKeyboardType) -> some>>.0)>>, SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, <<opaque return type of SwiftUI.View.keyboardType(__C.UIKeyboardType) -> some>>.0)>>, SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, <<opaque return type of SwiftUI.View.keyboardType(__C.UIKeyboardType) -> some>>.0)>>)>, SwiftUI.EmptyView>, SwiftUI.Section<SwiftUI.Text, SwiftUI.TupleView<(SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, SwiftUI.Text)>>, SwiftUI.Button<SwiftUI.Text>, SwiftUI.NavigationLink<SwiftUI.Text, StosVPN.HelpView>)>, SwiftUI.EmptyView>)> in closure #1 () -> <<opaque return type of SwiftUI.View.toolbar<τ_0_0 where τ_1_0: SwiftUI.ToolbarContent>(content: () -> τ_1_0) -> some>>.0 in StosVPN.SettingsView.body.getter : some"
|
||||
moduleName = "StosVPN.debug.dylib"
|
||||
usesParentBreakpointCondition = "Yes"
|
||||
urlString = "file:///Users/stossy11/Developer/StosVPN/StosVPN/ContentView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "613"
|
||||
endingLineNumber = "613">
|
||||
</Location>
|
||||
<Location
|
||||
uuid = "EBA30226-5BCA-4729-8062-C41AF6A700D2 - e2b02a9d9e8fd01"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
symbolName = "closure #2 @Swift.MainActor () -> () in closure #3 () -> SwiftUI.TupleView<(SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, SwiftUI.Text)>>, SwiftUI.Button<SwiftUI.Text>, SwiftUI.NavigationLink<SwiftUI.Text, StosVPN.HelpView>)> in closure #1 () -> SwiftUI.TupleView<(SwiftUI.Section<SwiftUI.Text, SwiftUI.TupleView<(SwiftUI.Toggle<SwiftUI.Text>, SwiftUI.NavigationLink<SwiftUI.Label<SwiftUI.Text, SwiftUI.Image>, StosVPN.ConnectionLogView>)>, SwiftUI.EmptyView>, SwiftUI.Section<SwiftUI.Text, SwiftUI.TupleView<(SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, <<opaque return type of SwiftUI.View.keyboardType(__C.UIKeyboardType) -> some>>.0)>>, SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, <<opaque return type of SwiftUI.View.keyboardType(__C.UIKeyboardType) -> some>>.0)>>, SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, <<opaque return type of SwiftUI.View.keyboardType(__C.UIKeyboardType) -> some>>.0)>>)>, SwiftUI.EmptyView>, SwiftUI.Section<SwiftUI.Text, SwiftUI.TupleView<(SwiftUI.HStack<SwiftUI.TupleView<(SwiftUI.Text, SwiftUI.Spacer, SwiftUI.Text)>>, SwiftUI.Button<SwiftUI.Text>, SwiftUI.NavigationLink<SwiftUI.Text, StosVPN.HelpView>)>, SwiftUI.EmptyView>)> in closure #1 () -> <<opaque return type of SwiftUI.View.toolbar<τ_0_0 where τ_1_0: SwiftUI.ToolbarContent>(content: () -> τ_1_0) -> some>>.0 in StosVPN.SettingsView.body.getter : some"
|
||||
moduleName = "StosVPN.debug.dylib"
|
||||
usesParentBreakpointCondition = "Yes"
|
||||
urlString = "file:///Users/stossy11/Developer/StosVPN/StosVPN/ContentView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "614"
|
||||
endingLineNumber = "614">
|
||||
</Location>
|
||||
</Locations>
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
||||
@@ -297,6 +297,7 @@ struct ContentView: View {
|
||||
@State private var showSettings = false
|
||||
@State var tunnel = false
|
||||
@AppStorage("autoConnect") private var autoConnect = false
|
||||
@AppStorage("hasNotCompletedSetup") private var hasNotCompletedSetup = true
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
@@ -335,10 +336,12 @@ struct ContentView: View {
|
||||
tunnelManager.startVPN()
|
||||
}
|
||||
}
|
||||
|
||||
.sheet(isPresented: $showSettings) {
|
||||
SettingsView()
|
||||
}
|
||||
.sheet(isPresented: $hasNotCompletedSetup) {
|
||||
SetupView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -607,8 +610,8 @@ struct SettingsView: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
NavigationLink(destination: PrivacyPolicyView()) {
|
||||
Text("Privacy Policy")
|
||||
Button("Privacy Policy") {
|
||||
UIApplication.shared.open(URL(string: "https://github.com/stossy11/PrivacyPolicy/blob/main/PrivacyPolicy.md")!)
|
||||
}
|
||||
|
||||
NavigationLink(destination: HelpView()) {
|
||||
@@ -727,6 +730,151 @@ struct HelpView: View {
|
||||
}
|
||||
}
|
||||
|
||||
struct SetupView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@AppStorage("hasNotCompletedSetup") private var hasNotCompletedSetup = true
|
||||
@State private var currentPage = 0
|
||||
|
||||
let pages = [
|
||||
SetupPage(
|
||||
title: "Welcome to StosVPN",
|
||||
description: "A simple local network tunnel for everyone",
|
||||
imageName: "checkmark.shield.fill",
|
||||
details: "StosVPN creates a local network interface on your device that anyone can use for development, testing, and accessing local servers."
|
||||
),
|
||||
SetupPage(
|
||||
title: "Why Use StosVPN?",
|
||||
description: "Perfect for developers and everyday users",
|
||||
imageName: "person.2.fill",
|
||||
details: "• Access local web servers and development environments\n• Test applications that require specific network configurations\n• Connect to local network services without complex setup\n• Create isolated network environments for testing"
|
||||
),
|
||||
SetupPage(
|
||||
title: "Easy to Use",
|
||||
description: "Just one tap to connect",
|
||||
imageName: "hand.tap.fill",
|
||||
details: "StosVPN is designed to be simple and straightforward. Just tap the connect button to establish a local network tunnel with pre-configured settings that work for most users."
|
||||
),
|
||||
SetupPage(
|
||||
title: "Privacy Focused",
|
||||
description: "Your data stays on your device",
|
||||
imageName: "lock.shield.fill",
|
||||
details: "StosVPN creates a local tunnel that doesn't route traffic through external servers. All network traffic remains on your device, ensuring your privacy and security."
|
||||
)
|
||||
]
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
TabView(selection: $currentPage) {
|
||||
ForEach(0..<pages.count, id: \.self) { index in
|
||||
SetupPageView(page: pages[index])
|
||||
.tag(index)
|
||||
}
|
||||
}
|
||||
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
|
||||
|
||||
Spacer()
|
||||
|
||||
if currentPage == pages.count - 1 {
|
||||
Button {
|
||||
hasNotCompletedSetup = false
|
||||
dismiss()
|
||||
} label: {
|
||||
Text("Get Started")
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.frame(height: 50)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [Color.blue.opacity(0.8), Color.blue]),
|
||||
startPoint: .leading,
|
||||
endPoint: .trailing
|
||||
)
|
||||
)
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(10)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.padding(.bottom)
|
||||
} else {
|
||||
Button {
|
||||
withAnimation {
|
||||
currentPage += 1
|
||||
}
|
||||
} label: {
|
||||
Text("Next")
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
.frame(height: 50)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [Color.blue.opacity(0.8), Color.blue]),
|
||||
startPoint: .leading,
|
||||
endPoint: .trailing
|
||||
)
|
||||
)
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(10)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Setup")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button("Skip") {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SetupPage {
|
||||
let title: String
|
||||
let description: String
|
||||
let imageName: String
|
||||
let details: String
|
||||
}
|
||||
|
||||
struct SetupPageView: View {
|
||||
let page: SetupPage
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 30) {
|
||||
Image(systemName: page.imageName)
|
||||
.font(.system(size: 80))
|
||||
.foregroundColor(.blue)
|
||||
.padding(.top, 50)
|
||||
|
||||
Text(page.title)
|
||||
.font(.title)
|
||||
.fontWeight(.bold)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
Text(page.description)
|
||||
.font(.headline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
ScrollView {
|
||||
Text(page.details)
|
||||
.font(.body)
|
||||
.multilineTextAlignment(.leading)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user