修复到第一版的UI
3
dmg.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#! /bin/sh
|
||||
|
||||
create-dmg --volname "punchnet" --window-pos 200 120 --window-size 800 400 --icon "punchnet.app" 200 190 --hide-extension "punchnet.app" --app-drop-link 600 185 ~/Desktop/punchnet.dmg /Users/anlicheng/Desktop/sdlan_v1
|
||||
@ -1,46 +1,55 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "logo.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_32 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_64.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_256 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "logo_512 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
|
||||
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_128.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_256 1.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_256.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_32 1.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_32.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_512 1.png
Normal file
|
After Width: | Height: | Size: 276 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_512.png
Normal file
|
After Width: | Height: | Size: 276 KiB |
BIN
punchnet/Assets.xcassets/AppIcon.appiconset/logo_64.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
21
punchnet/Assets.xcassets/IosSettings.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "IosSettings.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
8
punchnet/Assets.xcassets/IosSettings.imageset/IosSettings.svg
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<svg version="1.1" fill="#fff" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path d="M416.3,256c0-21,13.1-38.9,31.7-46.1c-4.9-20.5-13-39.7-23.7-57.1c-6.4,2.8-13.2,4.3-20.1,4.3c-12.6,0-25.2-4.8-34.9-14.4
|
||||
c-14.9-14.9-18.2-36.8-10.2-55C341.8,77,322.5,68.9,302.1,64C295,82.5,277,95.7,256,95.7c-21,0-39-13.2-46.1-31.7
|
||||
c-20.5,4.9-39.7,13-57.1,23.7c8.1,18.1,4.7,40.1-10.2,55c-9.6,9.6-22.3,14.4-34.9,14.4c-6.9,0-13.7-1.4-20.1-4.3
|
||||
C77,170.3,68.9,189.5,64,210c18.5,7.1,31.7,25,31.7,46.1c0,21-13.1,38.9-31.6,46.1c4.9,20.5,13,39.7,23.7,57.1
|
||||
c6.4-2.8,13.2-4.2,20-4.2c12.6,0,25.2,4.8,34.9,14.4c14.8,14.8,18.2,36.8,10.2,54.9c17.4,10.7,36.7,18.8,57.1,23.7
|
||||
c7.1-18.5,25-31.6,46-31.6c21,0,38.9,13.1,46,31.6c20.5-4.9,39.7-13,57.1-23.7c-8-18.1-4.6-40,10.2-54.9
|
||||
c9.6-9.6,22.2-14.4,34.9-14.4c6.8,0,13.7,1.4,20,4.2c10.7-17.4,18.8-36.7,23.7-57.1C429.5,295,416.3,277.1,416.3,256z M256.9,335.9
|
||||
c-44.3,0-80-35.9-80-80c0-44.1,35.7-80,80-80s80,35.9,80,80C336.9,300,301.2,335.9,256.9,335.9z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
21
punchnet/Assets.xcassets/close.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "close.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
punchnet/Assets.xcassets/close.imageset/close.png
vendored
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
21
punchnet/Assets.xcassets/line.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "line.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
punchnet/Assets.xcassets/line.imageset/line.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
@ -1,7 +1,6 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "logo.jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
@ -12,6 +11,15 @@
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"filename" : "logo.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
||||
BIN
punchnet/Assets.xcassets/logo.imageset/logo.jpg
vendored
|
Before Width: | Height: | Size: 22 KiB |
BIN
punchnet/Assets.xcassets/logo.imageset/logo.png
vendored
Normal file
|
After Width: | Height: | Size: 216 KiB |
21
punchnet/Assets.xcassets/logo_32.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "logo_32.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
punchnet/Assets.xcassets/logo_32.imageset/logo_32.png
vendored
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
@ -10,67 +10,154 @@ import SwiftData
|
||||
import Combine
|
||||
|
||||
struct ContentView: View {
|
||||
//@Environment(\.modelContext) private var modelContext
|
||||
//@Query private var items: [Item]
|
||||
|
||||
@AppStorage("token") private var token: String = ""
|
||||
@State private var showToken: Bool = false
|
||||
|
||||
@ObservedObject private var vpnManager = VPNManager.shared
|
||||
@State private var showAlert = false
|
||||
@State private var showStunAlert = false
|
||||
@State private var message: NoticeMessage.InboundMessage = .none
|
||||
@State private var cancel: AnyCancellable?
|
||||
|
||||
|
||||
@State private var showMenu: Bool = false
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack(alignment: .center, spacing: 10) {
|
||||
|
||||
Image("logo")
|
||||
|
||||
Text("PUNCHENT")
|
||||
.font(.system(size: 46, weight: .bold))
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(5.0)
|
||||
VStack(alignment: .center, spacing: 10) {
|
||||
Spacer()
|
||||
.frame(height: 100)
|
||||
|
||||
Image("logo")
|
||||
.resizable()
|
||||
.frame(width: 150, height: 150)
|
||||
|
||||
Text("Connecting the Infinite")
|
||||
.font(.system(size: 24, weight: .bold))
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(5.0)
|
||||
|
||||
Text("Welcome to PunchNet")
|
||||
.font(.system(size: 14, weight: .regular))
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(5.0)
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
self.showMenu = false
|
||||
}
|
||||
|
||||
Spacer()
|
||||
.frame(width: 1, height: 10)
|
||||
|
||||
TextField("邀请码", text: $token)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(width: 245, height: 27)
|
||||
.cornerRadius(5.0)
|
||||
if showToken {
|
||||
TextField("邀请码", text: $token)
|
||||
.multilineTextAlignment(.leading)
|
||||
.textFieldStyle(PlainTextFieldStyle())
|
||||
.frame(width: 200, height: 25)
|
||||
.background(Color.white)
|
||||
.foregroundColor(Color.black)
|
||||
.cornerRadius(5.0)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
.frame(width: 1, height: 10)
|
||||
|
||||
Button(action: {
|
||||
Task {
|
||||
switch self.vpnManager.vpnStatus {
|
||||
case .connected:
|
||||
try await vpnManager.disableVpn()
|
||||
case .disconnected:
|
||||
if self.token.isEmpty {
|
||||
self.showAlert = true
|
||||
return
|
||||
}
|
||||
try await vpnManager.enableVpn(options: [
|
||||
"version:": SystemConfig.version as NSObject,
|
||||
"installed_channel": SystemConfig.installedChannel as NSObject,
|
||||
"token": self.token as NSObject
|
||||
])
|
||||
Rectangle()
|
||||
.overlay {
|
||||
Text(vpnManager.title)
|
||||
.font(.system(size: 14, weight: .regular))
|
||||
.foregroundColor(vpnManager.color)
|
||||
}
|
||||
.frame(width: 120, height: 35)
|
||||
.foregroundColor(Color(red: 74 / 255, green: 207 / 255, blue: 154 / 255))
|
||||
.cornerRadius(5.0)
|
||||
.onTapGesture {
|
||||
Task {
|
||||
try await self.clickSwitchButton()
|
||||
}
|
||||
}
|
||||
}, label: {
|
||||
Text(vpnManager.title)
|
||||
.font(.system(size: 16, weight: .regular))
|
||||
.foregroundColor(vpnManager.color)
|
||||
.cornerRadius(5.0)
|
||||
})
|
||||
.frame(width: 138, height: 33)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.background(Color(red: 74 / 255, green: 207 / 255, blue: 154 / 255))
|
||||
.cornerRadius(5.0)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(width: 380, height: 560)
|
||||
.overlay(alignment: .top) {
|
||||
|
||||
HStack(spacing: 200) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
NSApplication.shared.terminate(nil)
|
||||
}) {
|
||||
|
||||
Image("close")
|
||||
.resizable()
|
||||
.frame(width: 15, height: 15)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
|
||||
Button(action: {
|
||||
NSApplication.shared.keyWindow?.miniaturize(nil)
|
||||
}) {
|
||||
Image("line")
|
||||
.resizable()
|
||||
.frame(width: 15, height: 15)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
showMenu.toggle()
|
||||
}) {
|
||||
Image("IosSettings")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.overlay(alignment: .leading) {
|
||||
showMenu ?
|
||||
|
||||
GeometryReader { geometry in
|
||||
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Button(action: {
|
||||
self.showMenu = false
|
||||
}) {
|
||||
Text("主页")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
|
||||
Button(action: {
|
||||
self.showToken.toggle()
|
||||
}) {
|
||||
Text("邀请码")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
|
||||
Button(action: {
|
||||
NSApplication.shared.terminate(nil)
|
||||
}) {
|
||||
Text("退出")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
.frame(width: 90, height: 80)
|
||||
.background(Color(red: 50 / 255, green: 55 / 255, blue: 52 / 255))
|
||||
.offset(x: -55, y: 20)
|
||||
}
|
||||
|
||||
: nil
|
||||
}
|
||||
|
||||
}
|
||||
.offset(x: 0, y: 10)
|
||||
}
|
||||
.frame(width: 300, height: 500)
|
||||
.background(Color(red: 36 / 255, green: 38 / 255, blue: 51 / 255))
|
||||
.alert(isPresented: $showAlert) {
|
||||
Alert(title: Text("请输入正确的邀请码"))
|
||||
@ -93,51 +180,31 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
NavigationSplitView {
|
||||
List {
|
||||
ForEach(items) { item in
|
||||
NavigationLink {
|
||||
Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
|
||||
} label: {
|
||||
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
|
||||
}
|
||||
}
|
||||
.onDelete(perform: deleteItems)
|
||||
}
|
||||
.navigationSplitViewColumnWidth(min: 180, ideal: 200)
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button(action: addItem) {
|
||||
Label("Add Item", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
} detail: {
|
||||
Text("Select an item")
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
private func addItem() {
|
||||
withAnimation {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private func deleteItems(offsets: IndexSet) {
|
||||
withAnimation {
|
||||
// for index in offsets {
|
||||
// modelContext.delete(items[index])
|
||||
// }
|
||||
private func clickSwitchButton() async throws {
|
||||
switch self.vpnManager.vpnStatus {
|
||||
case .connected:
|
||||
try await vpnManager.disableVpn()
|
||||
case .disconnected:
|
||||
/*
|
||||
if self.token.isEmpty {
|
||||
self.showAlert = true
|
||||
return
|
||||
}
|
||||
*/
|
||||
//print("use port: \(vpnManager.noticePort as NSObject)")
|
||||
try await vpnManager.enableVpn(options: [
|
||||
"version:": SystemConfig.version as NSObject,
|
||||
"installed_channel": SystemConfig.installedChannel as NSObject,
|
||||
"token": self.token as NSObject
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
//.modelContainer(for: Item.self, inMemory: true)
|
||||
//.modelContainer(for: Item.self, inMemory: true)
|
||||
}
|
||||
|
||||