general: screw the close anim
This commit is contained in:
@@ -216,22 +216,43 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
|
||||
guard let self = self, let settingsManager = self.settingsManager else { return }
|
||||
|
||||
let window = NSWindow(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 700, height: 700),
|
||||
styleMask: [.titled, .closable, .miniaturizable],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
)
|
||||
// Check if onboarding window already exists from the WindowGroup
|
||||
let existingWindow = NSApplication.shared.windows.first { window in
|
||||
// Check if window contains OnboardingContainerView by examining its content view
|
||||
if let hostingView = window.contentView as? NSHostingView<OnboardingContainerView> {
|
||||
return true
|
||||
}
|
||||
// Also check for windows with our expected size (onboarding window dimensions)
|
||||
return window.frame.size.width == 700 && window.frame.size.height == 700
|
||||
&& window.styleMask.contains(.titled)
|
||||
&& window.title.isEmpty // WindowGroup windows have empty title by default
|
||||
}
|
||||
|
||||
window.title = "Gaze Onboarding"
|
||||
window.center()
|
||||
window.isReleasedWhenClosed = true
|
||||
window.contentView = NSHostingView(
|
||||
rootView: OnboardingContainerView(settingsManager: settingsManager)
|
||||
)
|
||||
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
if let window = existingWindow {
|
||||
// Reuse existing window - just bring it to front
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
} else {
|
||||
// Create new window matching WindowGroup style
|
||||
let window = NSWindow(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 700, height: 700),
|
||||
styleMask: [.titled, .closable, .miniaturizable, .fullSizeContentView],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
)
|
||||
|
||||
// Match the WindowGroup style: hiddenTitleBar
|
||||
window.titleVisibility = .hidden
|
||||
window.titlebarAppearsTransparent = true
|
||||
window.center()
|
||||
window.isReleasedWhenClosed = true
|
||||
window.contentView = NSHostingView(
|
||||
rootView: OnboardingContainerView(settingsManager: settingsManager)
|
||||
)
|
||||
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ struct OnboardingContainerView: View {
|
||||
@State private var postureIntervalMinutes = 30
|
||||
@State private var launchAtLogin = false
|
||||
@State private var subtleReminderSize: ReminderSize = .medium
|
||||
@State private var isAnimatingOut = false
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
@@ -151,8 +150,6 @@ struct OnboardingContainerView: View {
|
||||
}
|
||||
}
|
||||
.frame(minWidth: 1000, minHeight: 800)
|
||||
.opacity(isAnimatingOut ? 0 : 1)
|
||||
.scaleEffect(isAnimatingOut ? 0.3 : 1.0)
|
||||
}
|
||||
|
||||
private func completeOnboarding() {
|
||||
@@ -188,49 +185,19 @@ struct OnboardingContainerView: View {
|
||||
print("Failed to set launch at login: \(error)")
|
||||
}
|
||||
|
||||
// Perform vacuum animation
|
||||
performVacuumAnimation()
|
||||
}
|
||||
// Close window with standard macOS animation
|
||||
dismiss()
|
||||
|
||||
private func performVacuumAnimation() {
|
||||
// Get the NSWindow reference
|
||||
guard
|
||||
let window = NSApplication.shared.windows.first(where: {
|
||||
$0.isVisible && $0.contentView != nil
|
||||
})
|
||||
else {
|
||||
// Fallback: just dismiss without animation
|
||||
dismiss()
|
||||
return
|
||||
// After a brief delay, trigger the menu bar extra to open
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
||||
if let menuBarWindow = NSApp.windows.first(where: {
|
||||
$0.className.contains("MenuBarExtra") || $0.className.contains("StatusBar")
|
||||
}),
|
||||
let statusItem = menuBarWindow.value(forKey: "statusItem") as? NSStatusItem
|
||||
{
|
||||
statusItem.button?.performClick(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate target position (top-center of screen where menu bar is)
|
||||
let screen = NSScreen.main?.frame ?? .zero
|
||||
let targetRect = NSRect(
|
||||
x: screen.midX,
|
||||
y: screen.maxY,
|
||||
width: 0,
|
||||
height: 0
|
||||
)
|
||||
|
||||
// Start SwiftUI animation for visual effects
|
||||
withAnimation(.easeInOut(duration: 0.7)) {
|
||||
isAnimatingOut = true
|
||||
}
|
||||
|
||||
// Animate window frame using AppKit
|
||||
NSAnimationContext.runAnimationGroup(
|
||||
{ context in
|
||||
context.duration = 0.7
|
||||
context.timingFunction = CAMediaTimingFunction(name: .easeIn)
|
||||
window.animator().setFrame(targetRect, display: true)
|
||||
window.animator().alphaValue = 0
|
||||
},
|
||||
completionHandler: {
|
||||
// Close window after animation completes
|
||||
self.dismiss()
|
||||
window.close()
|
||||
})
|
||||
}
|
||||
}
|
||||
#Preview("Onboarding Container") {
|
||||
|
||||
Reference in New Issue
Block a user