diff --git a/punchnet/App/AppWindow.swift b/punchnet/App/AppWindow.swift new file mode 100644 index 0000000..17bbf8d --- /dev/null +++ b/punchnet/App/AppWindow.swift @@ -0,0 +1,62 @@ +// +// AppWindow.swift +// punchnet +// +// Created by Codex on 2026/5/26. +// + +import AppKit +import SwiftUI + +enum AppWindow { + static let main = "main" + static let settings = "settings" + + @MainActor + static func open(id: String, using openWindow: OpenWindowAction) { + openWindow(id: id) + bringToFront(id: id) + } + + @MainActor + static func bringToFront(id: String, attempt: Int = 0) { + NSApp.activate(ignoringOtherApps: true) + + if let window = NSApp.windows.first(where: { $0.identifier?.rawValue == id }) { + window.deminiaturize(nil) + window.makeKeyAndOrderFront(nil) + window.orderFrontRegardless() + return + } + + guard attempt < 6 else { + return + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { + Task { @MainActor in + bringToFront(id: id, attempt: attempt + 1) + } + } + } +} + +struct AppWindowIdentifier: NSViewRepresentable { + let id: String + + func makeNSView(context: Context) -> NSView { + let view = NSView(frame: .zero) + configure(view) + return view + } + + func updateNSView(_ nsView: NSView, context: Context) { + configure(nsView) + } + + private func configure(_ view: NSView) { + DispatchQueue.main.async { + view.window?.identifier = NSUserInterfaceItemIdentifier(self.id) + } + } +} diff --git a/punchnet/App/punchnetApp.swift b/punchnet/App/punchnetApp.swift index 6e59dc6..83f19c4 100644 --- a/punchnet/App/punchnetApp.swift +++ b/punchnet/App/punchnetApp.swift @@ -42,7 +42,7 @@ struct punchnetApp: App { } var body: some Scene { - Window("Punchnet", id: "main-\(SystemConfig.env.rawValue)") { + Window("Punchnet", id: AppWindow.main) { AppRootView() .navigationTitle("") .environment(self.appContext) @@ -50,6 +50,7 @@ struct punchnetApp: App { width: self.appContext.isLogined ? 900 : 380, height: self.appContext.isLogined ? 600 : 500 ) + .background(AppWindowIdentifier(id: AppWindow.main)) // 增加动画:当状态改变时,窗口会像微信那样丝滑地变大/变小 .animation(.spring(response: 0.4, dampingFraction: 0.8), value: self.appContext.isLogined) .onAppear { @@ -65,10 +66,11 @@ struct punchnetApp: App { .defaultPosition(.center) .windowStyle(.hiddenTitleBar) - Window("settings", id: "settings-\(SystemConfig.env.rawValue)") { + Window("settings", id: AppWindow.settings) { SettingsView() .environment(self.appContext) .frame(width: 750, height: 450) + .background(AppWindowIdentifier(id: AppWindow.settings)) } .windowResizability(.contentSize) .defaultPosition(.center) diff --git a/punchnet/Features/MenuBar/Views/MainMenuBar.swift b/punchnet/Features/MenuBar/Views/MainMenuBar.swift index e823469..fc54268 100644 --- a/punchnet/Features/MenuBar/Views/MainMenuBar.swift +++ b/punchnet/Features/MenuBar/Views/MainMenuBar.swift @@ -48,14 +48,12 @@ struct MainMenuBar: View { Divider() Button("打开控制面板") { - openWindow(id: "main-\(SystemConfig.env.rawValue)") - NSApp.activate(ignoringOtherApps: true) + AppWindow.open(id: AppWindow.main, using: openWindow) print("call me open main") } Button("设置") { - openWindow(id: "settings-\(SystemConfig.env.rawValue)") - NSApp.activate(ignoringOtherApps: true) + AppWindow.open(id: AppWindow.settings, using: openWindow) } Divider() diff --git a/punchnet/Features/Network/Views/NetworkView.swift b/punchnet/Features/Network/Views/NetworkView.swift index 3aae6e6..df5e9d1 100644 --- a/punchnet/Features/Network/Views/NetworkView.swift +++ b/punchnet/Features/Network/Views/NetworkView.swift @@ -46,7 +46,7 @@ struct NetworkView: View { } Button { - openWindow(id: "settings") + AppWindow.open(id: AppWindow.settings, using: openWindow) } label: { Image(systemName: "slider.horizontal.3") .font(.system(size: 14)) diff --git a/punchnet/Features/Settings/Views/SettingsAccountView.swift b/punchnet/Features/Settings/Views/SettingsAccountView.swift index 3495e18..90373f2 100644 --- a/punchnet/Features/Settings/Views/SettingsAccountView.swift +++ b/punchnet/Features/Settings/Views/SettingsAccountView.swift @@ -28,7 +28,7 @@ struct SettingsAccountView: View { } else { // 蓝色主按钮 Button { - self.openWindow(id: "main") + AppWindow.open(id: AppWindow.main, using: openWindow) } label: { Text("登录") .fontWeight(.medium) @@ -115,8 +115,8 @@ private struct AccountCreditView: View { try await appContext.logout() } self.appContext.appScene = .login(username: username) - self.dismissWindow(id: "settings") - self.openWindow(id: "main") + self.dismissWindow(id: AppWindow.settings) + AppWindow.open(id: AppWindow.main, using: openWindow) } .buttonStyle(.bordered) .foregroundColor(.red) @@ -141,8 +141,8 @@ private struct TokenCreditView: View { } self.appContext.appScene = .login(username: nil) - self.dismissWindow(id: "settings") - self.openWindow(id: "main") + self.dismissWindow(id: AppWindow.settings) + AppWindow.open(id: AppWindow.main, using: openWindow) } .buttonStyle(.bordered) .foregroundColor(.red)