Remove Hober Animation and toggle states; implement always-expanded state for mini-recorder

This commit is contained in:
Beingpax 2025-08-08 19:40:35 +05:45
parent c37dfb09a1
commit 95c82f0014
3 changed files with 15 additions and 138 deletions

View File

@ -30,14 +30,12 @@ class MiniRecorderPanel: NSPanel {
standardWindowButton(.closeButton)?.isHidden = true
}
static func calculateWindowMetrics(expanded: Bool = false) -> NSRect {
static func calculateWindowMetrics() -> NSRect {
guard let screen = NSScreen.main else {
return NSRect(x: 0, y: 0, width: expanded ? 160 : 70, height: 34)
return NSRect(x: 0, y: 0, width: 160, height: 34)
}
let compactWidth: CGFloat = 100
let expandedWidth: CGFloat = 160
let width = expanded ? expandedWidth : compactWidth
let width: CGFloat = 160
let height: CGFloat = 34
let padding: CGFloat = 24
@ -55,29 +53,11 @@ class MiniRecorderPanel: NSPanel {
}
func show() {
let metrics = MiniRecorderPanel.calculateWindowMetrics(expanded: false)
let metrics = MiniRecorderPanel.calculateWindowMetrics()
setFrame(metrics, display: true)
orderFrontRegardless()
}
func expandWindow(completion: (() -> Void)? = nil) {
let expandedMetrics = MiniRecorderPanel.calculateWindowMetrics(expanded: true)
NSAnimationContext.runAnimationGroup({ context in
context.duration = 0.25
context.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
animator().setFrame(expandedMetrics, display: true)
}, completionHandler: completion)
}
func collapseWindow(completion: (() -> Void)? = nil) {
let compactMetrics = MiniRecorderPanel.calculateWindowMetrics(expanded: false)
NSAnimationContext.runAnimationGroup({ context in
context.duration = 0.25
context.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
animator().setFrame(compactMetrics, display: true)
}, completionHandler: completion)
}
func hide(completion: @escaping () -> Void) {
completion()
}

View File

@ -8,12 +8,6 @@ struct MiniRecorderView: View {
@State private var showPowerModePopover = false
@State private var showEnhancementPromptPopover = false
@State private var isHovering = false
// Computed property to check if any popover is currently showing
private var isAnyPopoverShowing: Bool {
showPowerModePopover || showEnhancementPromptPopover
}
private var backgroundView: some View {
ZStack {
@ -41,27 +35,21 @@ struct MiniRecorderView: View {
private var contentLayout: some View {
HStack(spacing: 0) {
if windowManager.isExpanded {
// Left button zone - only exists when expanded
RecorderPromptButton(showPopover: $showEnhancementPromptPopover)
.padding(.leading, 6)
.transition(.scale(scale: 0.5).combined(with: .opacity))
Spacer()
}
// Left button zone - always visible
RecorderPromptButton(showPopover: $showEnhancementPromptPopover)
.padding(.leading, 6)
// Fixed visualizer zone - takes full width when compact
Spacer()
// Fixed visualizer zone
statusView
.frame(maxWidth: .infinity)
if windowManager.isExpanded {
Spacer()
// Right button zone - only exists when expanded
RecorderPowerModeButton(showPopover: $showPowerModePopover)
.padding(.trailing, 6)
.transition(.scale(scale: 0.5).combined(with: .opacity))
}
Spacer()
// Right button zone - always visible
RecorderPowerModeButton(showPopover: $showPowerModePopover)
.padding(.trailing, 6)
}
.padding(.vertical, 8)
}
@ -83,25 +71,6 @@ struct MiniRecorderView: View {
Group {
if windowManager.isVisible {
recorderCapsule
.onHover { hovering in
isHovering = hovering
if hovering {
windowManager.expand()
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) {
// Only collapse if not hovering AND no popover is showing
if !isHovering && !isAnyPopoverShowing {
windowManager.collapse()
}
}
}
}
.onAppear {
// Set up the callback so WindowManager can check popover and hover state
windowManager.shouldPreventCollapse = {
isAnyPopoverShowing || isHovering
}
}
}
}
}

View File

@ -3,18 +3,11 @@ import AppKit
class MiniWindowManager: ObservableObject {
@Published var isVisible = false
@Published var isExpanded = false
private var windowController: NSWindowController?
private var miniPanel: MiniRecorderPanel?
private let whisperState: WhisperState
private let recorder: Recorder
// Callback to check if collapse should be prevented (e.g., when popovers are showing)
var shouldPreventCollapse: (() -> Bool)?
// Debounced timer for auto-collapse
private var debounceTimer: Timer?
init(whisperState: WhisperState, recorder: Recorder) {
self.whisperState = whisperState
self.recorder = recorder
@ -22,7 +15,6 @@ class MiniWindowManager: ObservableObject {
}
deinit {
debounceTimer?.invalidate()
NotificationCenter.default.removeObserver(self)
}
@ -33,50 +25,11 @@ class MiniWindowManager: ObservableObject {
name: NSNotification.Name("HideMiniRecorder"),
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleFeedbackNotification),
name: .promptSelectionChanged,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleFeedbackNotification),
name: .powerModeConfigurationApplied,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleFeedbackNotification),
name: .enhancementToggleChanged,
object: nil
)
}
@objc private func handleHideNotification() {
hide()
}
@objc private func handleFeedbackNotification() {
guard isVisible else { return }
// Only expand if not already expanded
if !isExpanded {
expand()
}
// Reset debounce timer - this cancels any existing timer and starts a new one
debounceTimer?.invalidate()
debounceTimer = Timer.scheduledTimer(withTimeInterval: 2.5, repeats: false) { [weak self] _ in
guard let self = self else { return }
if self.isExpanded && !(self.shouldPreventCollapse?() ?? false) {
self.collapse()
}
}
}
func show() {
if isVisible { return }
@ -87,35 +40,10 @@ class MiniWindowManager: ObservableObject {
miniPanel?.show()
}
func expand() {
guard isVisible, !isExpanded else { return }
withAnimation(.easeInOut(duration: 0.25)) {
isExpanded = true
}
miniPanel?.expandWindow()
}
func collapse() {
guard isVisible, isExpanded else { return }
withAnimation(.easeInOut(duration: 0.25)) {
isExpanded = false
}
miniPanel?.collapseWindow()
}
func hide() {
guard isVisible else { return }
// Cancel any pending auto-collapse timer
debounceTimer?.invalidate()
debounceTimer = nil
self.isVisible = false
self.isExpanded = false
self.miniPanel?.hide { [weak self] in
guard let self = self else { return }
self.deinitializeWindow()