From 581140d4dad99da4175db798ec464f8b082365bf Mon Sep 17 00:00:00 2001 From: h Date: Sat, 26 Sep 2026 18:28:24 +0200 Subject: [PATCH] fix(mac): toolbar strip with inspector, player close button and titlebar --- Amphlify/UI/Components/Chrome.swift | 1 + Amphlify/UI/Components/CollectionHeader.swift | 1 + Amphlify/UI/Detail/ArtistDetailView.swift | 1 + Amphlify/UI/Mac/MacNowPlayingView.swift | 13 +------- Amphlify/UI/Mac/MacRootView.swift | 19 +++++++++++- Amphlify/UI/Mac/MacTitlebarArea.swift | 31 +++++++++++++++++++ 6 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 Amphlify/UI/Mac/MacTitlebarArea.swift diff --git a/Amphlify/UI/Components/Chrome.swift b/Amphlify/UI/Components/Chrome.swift index 3f140ea..3aa4d31 100644 --- a/Amphlify/UI/Components/Chrome.swift +++ b/Amphlify/UI/Components/Chrome.swift @@ -140,6 +140,7 @@ private struct PageTitle: ViewModifier { .padding(.horizontal, Metrics.margin) .padding(.bottom, 8) } + .toolbarBackgroundVisibility(.hidden, for: .windowToolbar) #else content.navigationTitle(title) #endif diff --git a/Amphlify/UI/Components/CollectionHeader.swift b/Amphlify/UI/Components/CollectionHeader.swift index 50fa7cf..a4d6911 100644 --- a/Amphlify/UI/Components/CollectionHeader.swift +++ b/Amphlify/UI/Components/CollectionHeader.swift @@ -96,6 +96,7 @@ struct ScrollRevealedTitle: ViewModifier { .toolbarTitleDisplayMode(.inline) #if os(macOS) .toolbar(removing: .title) + .toolbarBackgroundVisibility(.hidden, for: .windowToolbar) .toolbar { ToolbarItem(placement: .principal) { Text(title).font(.headline).lineLimit(1).opacity(isRevealed ? 1 : 0) diff --git a/Amphlify/UI/Detail/ArtistDetailView.swift b/Amphlify/UI/Detail/ArtistDetailView.swift index 70568be..6a85ccd 100644 --- a/Amphlify/UI/Detail/ArtistDetailView.swift +++ b/Amphlify/UI/Detail/ArtistDetailView.swift @@ -16,6 +16,7 @@ struct ArtistDetailView: View { MacArtistPage(id: id, artist: artist, albums: albums, tracks: topTracks) } .background { Backdrop(artwork: artist?.artwork) } + .scrollEdgeEffectHidden(true, for: .top) .modifier(ScrollRevealedTitle(title: artist?.name ?? "", threshold: 120)) .task(id: app.revision) { artist = await app.library.artist(id) diff --git a/Amphlify/UI/Mac/MacNowPlayingView.swift b/Amphlify/UI/Mac/MacNowPlayingView.swift index 2a0d828..661ed16 100644 --- a/Amphlify/UI/Mac/MacNowPlayingView.swift +++ b/Amphlify/UI/Mac/MacNowPlayingView.swift @@ -23,7 +23,7 @@ } .animation(reduceMotion ? nil : .spring(response: 0.4, dampingFraction: 1), value: mode) } - .overlay(alignment: .topLeading) { windowButtons } + .overlay(alignment: .top) { MacTitlebarArea().frame(height: 52) } .overlay(alignment: .topTrailing) { output } .overlay(alignment: .bottomTrailing) { modeToggles } .background { Backdrop(artwork: player.current?.artwork) } @@ -53,17 +53,6 @@ } } - private var windowButtons: some View { - Button("Close", systemImage: "xmark") { router.showsNowPlaying = false } - .labelStyle(.iconOnly) - .buttonStyle(MacPlayerButtonStyle()) - .font(.system(size: 16, weight: .medium)) - .frame(width: 38, height: 36) - .glassEffect(.regular, in: .capsule) - .padding(.leading, 100) - .padding(.top, 8) - } - private var output: some View { HStack(spacing: 12) { RoutePicker().frame(width: 24, height: 24).accessibilityLabel("AirPlay") diff --git a/Amphlify/UI/Mac/MacRootView.swift b/Amphlify/UI/Mac/MacRootView.swift index 346f014..a0fd8d4 100644 --- a/Amphlify/UI/Mac/MacRootView.swift +++ b/Amphlify/UI/Mac/MacRootView.swift @@ -14,7 +14,7 @@ MacSidebar(selection: Binding { selection } set: { select($0) }) .toolbar(removing: .sidebarToggle) .toolbar { - ToolbarItem(id: MacWindowChrome.anchor) { Color.clear.frame(width: 1, height: 1) } + ToolbarItem(id: MacWindowChrome.anchor) { MacCloseButton() } .sharedBackgroundVisibility(.hidden) } } detail: { @@ -76,6 +76,23 @@ } } + private struct MacCloseButton: View { + @Environment(Router.self) private var router + + var body: some View { + Button("Close", systemImage: "xmark") { router.showsNowPlaying = false } + .labelStyle(.iconOnly) + .buttonStyle(MacPlayerButtonStyle()) + .font(.system(size: 16, weight: .medium)) + .frame(width: 38, height: 36) + .glassEffect(.regular, in: .capsule) + .environment(\.colorScheme, .dark) + .opacity(router.showsNowPlaying ? 1 : 0) + .allowsHitTesting(router.showsNowPlaying) + .accessibilityHidden(!router.showsNowPlaying) + } + } + private struct MacPlaybackKeys: ViewModifier { @Environment(Router.self) private var router @Environment(PlayerModel.self) private var player diff --git a/Amphlify/UI/Mac/MacTitlebarArea.swift b/Amphlify/UI/Mac/MacTitlebarArea.swift new file mode 100644 index 0000000..0267d75 --- /dev/null +++ b/Amphlify/UI/Mac/MacTitlebarArea.swift @@ -0,0 +1,31 @@ +#if os(macOS) + import AppKit + import SwiftUI + + struct MacTitlebarArea: NSViewRepresentable { + func makeNSView(context _: Context) -> TitlebarView { + TitlebarView() + } + + func updateNSView(_: TitlebarView, context _: Context) {} + + final class TitlebarView: NSView { + override var mouseDownCanMoveWindow: Bool { + false + } + + override func mouseDown(with event: NSEvent) { + guard let window else { return } + guard event.clickCount == 2 else { + window.performDrag(with: event) + return + } + switch UserDefaults.standard.string(forKey: "AppleActionOnDoubleClick") { + case "Minimize": window.performMiniaturize(nil) + case "None": break + default: window.performZoom(nil) + } + } + } + } +#endif