完善UI
This commit is contained in:
parent
2f2c5420e2
commit
d6e6c961a2
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct LoginRootView: View {
|
struct AppRootView: View {
|
||||||
@Environment(AppContext.self) var appContext: AppContext
|
@Environment(AppContext.self) var appContext: AppContext
|
||||||
@State private var updateManager = AppUpdateManager.shared
|
@State private var updateManager = AppUpdateManager.shared
|
||||||
|
|
||||||
62
punchnet/Views/Common/CustomWindowControls.swift
Normal file
62
punchnet/Views/Common/CustomWindowControls.swift
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// CustomWindowControls.swift
|
||||||
|
// punchnet
|
||||||
|
//
|
||||||
|
// Created by 安礼成 on 2026/3/25.
|
||||||
|
//
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct CustomWindowControls: View {
|
||||||
|
@State private var isHovering = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
// 关闭按钮 (红色)
|
||||||
|
CircleButton(color: .red, systemName: "xmark", isHovering: isHovering) {
|
||||||
|
// 执行关闭当前窗口的操作
|
||||||
|
if let window = NSApp.keyWindow {
|
||||||
|
window.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 最小化按钮 (黄色)
|
||||||
|
// CircleButton(color: .yellow, systemName: "minus", isHovering: isHovering) {
|
||||||
|
// NSApp.keyWindow?.miniaturize(nil)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 全屏/放大按钮 (绿色)
|
||||||
|
// CircleButton(color: .green, systemName: "arrow.up.left.and.arrow.down.right", isHovering: isHovering) {
|
||||||
|
// NSApp.keyWindow?.toggleFullScreen(nil)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
.onHover { hovering in
|
||||||
|
withAnimation(.easeInOut(duration: 0.1)) {
|
||||||
|
isHovering = hovering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CircleButton: View {
|
||||||
|
let color: Color
|
||||||
|
let systemName: String
|
||||||
|
let isHovering: Bool
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: action) {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.fill(color.opacity(0.8))
|
||||||
|
.frame(width: 12, height: 12)
|
||||||
|
|
||||||
|
// 只有悬停时才显示里面的小图标,像原生一样
|
||||||
|
Image(systemName: systemName)
|
||||||
|
.font(.system(size: 8, weight: .bold))
|
||||||
|
.foregroundColor(.black.opacity(0.5))
|
||||||
|
.opacity(isHovering ? 1 : 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,13 +35,18 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationSplitView(columnVisibility: $columnVisibility) {
|
NavigationSplitView(columnVisibility: $columnVisibility, sidebar: {
|
||||||
// MARK: - 自定义侧边栏
|
// MARK: - 自定义侧边栏
|
||||||
VStack(alignment: .leading, spacing: 20) {
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
Text("设置")
|
Text("设置")
|
||||||
.font(.system(size: 24, weight: .bold))
|
.font(.system(size: 24, weight: .bold))
|
||||||
.padding(.horizontal, 16)
|
.padding(.horizontal, 16)
|
||||||
.padding(.top, 24)
|
.padding(.top, 45)
|
||||||
|
.overlay(alignment: .topLeading) {
|
||||||
|
CustomWindowControls()
|
||||||
|
.padding(.top, 12)
|
||||||
|
.padding(.leading, 12)
|
||||||
|
}
|
||||||
|
|
||||||
VStack(spacing: 4) {
|
VStack(spacing: 4) {
|
||||||
ForEach(MenuItem.allCases, id: \.self) { menu in
|
ForEach(MenuItem.allCases, id: \.self) { menu in
|
||||||
@ -61,45 +66,48 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
}
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||||
.background(VisualEffectView(material: .sidebar, blendingMode: .behindWindow))
|
.background(VisualEffectView(material: .sidebar, blendingMode: .behindWindow))
|
||||||
|
.toolbar(.hidden, for: .windowToolbar)
|
||||||
.navigationSplitViewColumnWidth(min: 180, ideal: 200, max: 250)
|
.navigationSplitViewColumnWidth(min: 180, ideal: 200, max: 250)
|
||||||
|
.ignoresSafeArea(.all)
|
||||||
|
|
||||||
} detail: {
|
}, detail: {
|
||||||
// MARK: - 详情页转场
|
// MARK: - 详情页转场
|
||||||
ZStack(alignment: .topLeading) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
// 背景保持统一
|
Group {
|
||||||
VisualEffectView(material: .hudWindow, blendingMode: .behindWindow)
|
// 使用 ID 辅助 SwiftUI 识别视图切换,触发 transition
|
||||||
.ignoresSafeArea()
|
switch self.selectedMenu {
|
||||||
|
case .accout:
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
SettingsAccountView()
|
||||||
Group {
|
case .network:
|
||||||
// 使用 ID 辅助 SwiftUI 识别视图切换,触发 transition
|
SettingsNetworkView()
|
||||||
switch self.selectedMenu {
|
case .device:
|
||||||
case .accout:
|
SettingsDeviceView()
|
||||||
SettingsAccountView()
|
case .system:
|
||||||
case .network:
|
SettingsSystemView()
|
||||||
SettingsNetworkView()
|
case .about:
|
||||||
case .device:
|
SettingsAboutView()
|
||||||
SettingsDeviceView()
|
|
||||||
case .system:
|
|
||||||
SettingsSystemView()
|
|
||||||
case .about:
|
|
||||||
SettingsAboutView()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.id(selectedMenu) // 关键:确保切换时触发转场
|
|
||||||
.transition(.asymmetric(
|
|
||||||
insertion: .move(edge: .bottom).combined(with: .opacity),
|
|
||||||
removal: .opacity
|
|
||||||
))
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
.padding(32) // 加大留白,显得更高级
|
.id(selectedMenu) // 关键:确保切换时触发转场
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
.transition(.asymmetric(
|
||||||
|
insertion: .move(edge: .bottom).combined(with: .opacity),
|
||||||
|
removal: .opacity
|
||||||
|
))
|
||||||
|
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
.padding(32) // 加大留白,显得更高级
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||||
|
.toolbar(.hidden, for: .windowToolbar)
|
||||||
|
.ignoresSafeArea(edges: .top)
|
||||||
|
})
|
||||||
|
.navigationSplitViewStyle(.prominentDetail)
|
||||||
|
.background(VisualEffectView(material: .sidebar, blendingMode: .behindWindow))
|
||||||
|
.ignoresSafeArea(.all)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - 子组件:侧边栏按钮样式
|
// MARK: - 子组件:侧边栏按钮样式
|
||||||
|
|||||||
@ -45,7 +45,7 @@ struct punchnetApp: App {
|
|||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
Window("Punchnet", id: "main") {
|
Window("Punchnet", id: "main") {
|
||||||
LoginRootView()
|
AppRootView()
|
||||||
.navigationTitle("")
|
.navigationTitle("")
|
||||||
.environment(self.appContext)
|
.environment(self.appContext)
|
||||||
.frame(
|
.frame(
|
||||||
@ -70,10 +70,11 @@ struct punchnetApp: App {
|
|||||||
Settings {
|
Settings {
|
||||||
SettingsView()
|
SettingsView()
|
||||||
.environment(self.appContext)
|
.environment(self.appContext)
|
||||||
.frame(width: 750, height: 500)
|
.frame(width: 750, height: 450)
|
||||||
}
|
}
|
||||||
.windowResizability(.contentSize)
|
.windowResizability(.contentSize)
|
||||||
.defaultPosition(.center)
|
.defaultPosition(.center)
|
||||||
|
.windowStyle(.hiddenTitleBar)
|
||||||
|
|
||||||
MenuBarExtra("Punchnet", image: "logo_32") {
|
MenuBarExtra("Punchnet", image: "logo_32") {
|
||||||
MainMenuBar()
|
MainMenuBar()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user