From bfc88eac084576cbee54f790989a3a66f106230c Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Thu, 15 Jan 2026 17:21:21 +0800 Subject: [PATCH] fix login view --- Tun/Punchnet/SDLMessage.pb.swift | 112 ++++++++++++++++++++++ punchnet/Views/LoginView.swift | 153 +++++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+) create mode 100644 punchnet/Views/LoginView.swift diff --git a/Tun/Punchnet/SDLMessage.pb.swift b/Tun/Punchnet/SDLMessage.pb.swift index 4c750c5..c988ec2 100644 --- a/Tun/Punchnet/SDLMessage.pb.swift +++ b/Tun/Punchnet/SDLMessage.pb.swift @@ -472,6 +472,36 @@ struct SDLStunProbeReply: Sendable { init() {} } +struct SDLArpRequest: Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var networkID: UInt32 = 0 + + var targetIp: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct SDLArpResponse: @unchecked Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var networkID: UInt32 = 0 + + var targetIp: UInt32 = 0 + + var targetMac: Data = Data() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + // MARK: - Code below here is support for the SwiftProtobuf runtime. extension SDLV4Info: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { @@ -1480,3 +1510,85 @@ extension SDLStunProbeReply: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem return true } } + +extension SDLArpRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "SDLArpRequest" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "network_id"), + 2: .standard(proto: "target_ip"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.networkID) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &self.targetIp) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.networkID != 0 { + try visitor.visitSingularUInt32Field(value: self.networkID, fieldNumber: 1) + } + if self.targetIp != 0 { + try visitor.visitSingularUInt32Field(value: self.targetIp, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SDLArpRequest, rhs: SDLArpRequest) -> Bool { + if lhs.networkID != rhs.networkID {return false} + if lhs.targetIp != rhs.targetIp {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension SDLArpResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "SDLArpResponse" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "network_id"), + 2: .standard(proto: "target_ip"), + 3: .standard(proto: "target_mac"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.networkID) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &self.targetIp) }() + case 3: try { try decoder.decodeSingularBytesField(value: &self.targetMac) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.networkID != 0 { + try visitor.visitSingularUInt32Field(value: self.networkID, fieldNumber: 1) + } + if self.targetIp != 0 { + try visitor.visitSingularUInt32Field(value: self.targetIp, fieldNumber: 2) + } + if !self.targetMac.isEmpty { + try visitor.visitSingularBytesField(value: self.targetMac, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SDLArpResponse, rhs: SDLArpResponse) -> Bool { + if lhs.networkID != rhs.networkID {return false} + if lhs.targetIp != rhs.targetIp {return false} + if lhs.targetMac != rhs.targetMac {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/punchnet/Views/LoginView.swift b/punchnet/Views/LoginView.swift new file mode 100644 index 0000000..800e6c9 --- /dev/null +++ b/punchnet/Views/LoginView.swift @@ -0,0 +1,153 @@ +// +// LoginView.swift +// punchnet +// +// Created by 安礼成 on 2026/1/15. +// + +import SwiftUI + +// 登陆页面 +struct LoginView: View { + @State private var token: String = "" + + @State private var account: String = "" + @State private var password: String = "" + + @State private var loginMode: LoginMode = .account + + enum LoginMode { + case token + case account + } + + var body: some View { + VStack { + Text("PunchNet") + + HStack(alignment: .center, spacing: 30) { + HStack { + Image("logo") + .resizable() + .clipped() + .frame(width: 25, height: 25) + + Text("密钥登陆") + .foregroundColor(loginMode == .token ? .blue : .black) + } + .contentShape(Rectangle()) + .onTapGesture { + self.loginMode = .token + } + + HStack { + Image("logo") + .resizable() + .clipped() + .frame(width: 25, height: 25) + Text("账户登陆") + .foregroundColor(loginMode == .account ? .blue : .black) + } + .contentShape(Rectangle()) + .onTapGesture { + self.loginMode = .account + } + } + + switch loginMode { + case .token: + LoginTokenView(token: self.$token) + case .account: + LoginAccountView(account: $account, password: $password) + } + + Spacer() + } + .frame(width: 400, height: 400) + } + +} + +struct LoginTokenView: View { + @Binding var token: String + + var body: some View { + TextField("认证密钥", text: $token) + .multilineTextAlignment(.leading) + .textFieldStyle(PlainTextFieldStyle()) + .frame(width: 200, height: 25) + .background(Color.clear) + .foregroundColor(Color.black) + .overlay( + Rectangle() + .frame(height: 1) + .foregroundColor(.blue) + .padding(.top, 25) + , alignment: .topLeading) + + Rectangle() + .overlay { + Text("登陆") + .font(.system(size: 14, weight: .regular)) + .foregroundColor(.black) + } + .frame(width: 120, height: 35) + .foregroundColor(Color(red: 74 / 255, green: 207 / 255, blue: 154 / 255)) + .cornerRadius(5.0) + .onTapGesture { + print("call me here") + } + } + +} + +struct LoginAccountView: View { + @Binding var account: String + @Binding var password: String + + var body: some View { + TextField("手机号/邮箱", text: $account) + .multilineTextAlignment(.leading) + .textFieldStyle(PlainTextFieldStyle()) + .frame(width: 200, height: 25) + .background(Color.clear) + .foregroundColor(Color.black) + .overlay( + Rectangle() + .frame(height: 1) + .foregroundColor(.blue) + .padding(.top, 25) + , alignment: .topLeading) + + TextField("密码", text: $account) + .multilineTextAlignment(.leading) + .textFieldStyle(PlainTextFieldStyle()) + .frame(width: 200, height: 25) + .background(Color.clear) + .foregroundColor(Color.black) + .overlay( + Rectangle() + .frame(height: 1) + .foregroundColor(.blue) + .padding(.top, 25) + , alignment: .topLeading) + + Rectangle() + .overlay { + Text("登陆") + .font(.system(size: 14, weight: .regular)) + .foregroundColor(.black) + } + .frame(width: 120, height: 35) + .foregroundColor(Color(red: 74 / 255, green: 207 / 255, blue: 154 / 255)) + .cornerRadius(5.0) + .onTapGesture { + print("call me here") + } + } + +} + +#Preview { + LoginView() +}