punchnet-macos/punchnet/Views/Network/NetworkMenuView.swift
2026-03-26 14:19:07 +08:00

132 lines
4.4 KiB
Swift

import SwiftUI
///
struct NetworkMenuPopup: View {
@Binding var isPresented: Bool
@State private var isNetworkEnabled = true
var body: some View {
VStack(alignment: .leading, spacing: 0) {
// 1. ()
HStack(spacing: 12) {
Image(systemName: "person.fill")
.font(.system(size: 14))
.frame(width: 34, height: 34)
.background(Color.gray.opacity(0.1))
.clipShape(Circle())
Text("test3")
.font(.system(size: 15, weight: .medium))
}
.padding(.horizontal, 16)
.padding(.vertical, 16)
Divider().opacity(0.3).padding(.horizontal, 16)
// 2.
VStack(spacing: 4) {
NetworkMenuRow(title: "管理平台")
.onTapGesture {
print("点击管理平台")
}
NetworkMenuRow(title: "我的网络", subtitle: "test的网络") {
Toggle("", isOn: $isNetworkEnabled)
.toggleStyle(.switch)
.scaleEffect(0.65)
.labelsHidden()
.tint(Color(red: 0.15, green: 0.2, blue: 0.3))
}
NetworkMenuRow(title: "出口节点", subtitle: "未选择")
NetworkMenuRow(title: "退出登录", showArrow: false)
.onTapGesture {
withAnimation(.easeOut(duration: 0.2)) {
isPresented = false
}
}
}
.padding(6) //
}
.frame(width: 240)
.background(
RoundedRectangle(cornerRadius: 14)
.fill(Color(NSColor.windowBackgroundColor))
)
.overlay(
RoundedRectangle(cornerRadius: 14)
.stroke(Color.gray.opacity(0.1), lineWidth: 1)
)
.shadow(color: .black.opacity(0.12), radius: 12, x: 0, y: 6)
}
}
/// ( Hover )
struct NetworkMenuRow<RightContent: View>: View {
let title: String
var subtitle: String? = nil
var showArrow: Bool = true
var rightContent: RightContent?
@State private var isHovering = false //
init(title: String, subtitle: String? = nil, showArrow: Bool = true) where RightContent == EmptyView {
self.init(title: title, subtitle: subtitle, showArrow: showArrow) {
EmptyView()
}
}
init(title: String, subtitle: String? = nil, showArrow: Bool = true, @ViewBuilder rightContent: () -> RightContent? = { nil }) {
self.title = title
self.subtitle = subtitle
self.showArrow = showArrow
self.rightContent = rightContent()
}
var body: some View {
HStack(spacing: 0) {
VStack(alignment: .leading, spacing: 2) {
Text(title)
.font(.system(size: 13.5))
.foregroundColor(.primary)
if let sub = subtitle {
Text(sub)
.font(.system(size: 11.5))
.foregroundColor(.secondary)
}
}
Spacer()
//
if let content = rightContent {
content
}
//
if showArrow {
Image(systemName: "chevron.right")
.font(.system(size: 9, weight: .bold))
.foregroundColor(.secondary.opacity(0.4))
.padding(.leading, 6)
}
}
.padding(.horizontal, 12)
.padding(.vertical, 10)
// --- ---
.background(
RoundedRectangle(cornerRadius: 8)
.fill(isHovering ? Color.gray.opacity(0.12) : Color.clear)
)
.onHover { hovering in
withAnimation(.easeInOut(duration: 0.15)) {
isHovering = hovering
}
}
// ------------------
.contentShape(Rectangle())
}
}