diff --git a/DynamicIsland/ContentView.swift b/DynamicIsland/ContentView.swift index 790abc7..8bb739e 100644 --- a/DynamicIsland/ContentView.swift +++ b/DynamicIsland/ContentView.swift @@ -1009,9 +1009,9 @@ struct ContentView: View { Image(nsImage: musicManager.albumArt) .resizable() .aspectRatio(contentMode: .fit) + .clipShape(RoundedRectangle(cornerRadius: musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? MusicPlayerImageSizes.cornerRadiusInset.closed/3.0 : MusicPlayerImageSizes.cornerRadiusInset.closed)) ) .clipped() - .clipShape(RoundedRectangle(cornerRadius: MusicPlayerImageSizes.cornerRadiusInset.closed)) .matchedGeometryEffect(id: "albumArt", in: albumArtNamespace) .albumArtFlip(angle: musicManager.flipAngle) albumArtBadge(for: secondary, badgeSize: badgeDisplaySize) diff --git a/DynamicIsland/Localizable.xcstrings b/DynamicIsland/Localizable.xcstrings index d8adb7d..31e415e 100644 --- a/DynamicIsland/Localizable.xcstrings +++ b/DynamicIsland/Localizable.xcstrings @@ -982,6 +982,9 @@ } } } + }, + "%0.1f" : { + }, "%d%%" : { "localizations" : { @@ -13767,6 +13770,7 @@ } }, "Enable album art parallax effect" : { + "extractionState" : "stale", "localizations" : { "ru" : { "stringUnit" : { @@ -25883,6 +25887,9 @@ } } } + }, + "Parallax Effect Intensity" : { + }, "Pause" : { "localizations" : { diff --git a/DynamicIsland/components/LockScreen/LockScreenMusicPanel.swift b/DynamicIsland/components/LockScreen/LockScreenMusicPanel.swift index 3d8ea23..2cc0227 100644 --- a/DynamicIsland/components/LockScreen/LockScreenMusicPanel.swift +++ b/DynamicIsland/components/LockScreen/LockScreenMusicPanel.swift @@ -296,23 +296,24 @@ struct LockScreenMusicPanel: View { private func albumArtButton(size: CGFloat, cornerRadius: CGFloat) -> some View { Button(action: toggleExpanded) { - ZStack(alignment: .bottomTrailing) { - albumArtImage(size: size, cornerRadius: cornerRadius) - if showAppIcon, let icon = lockScreenAppIcon { - icon - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: appIconSize, height: appIconSize) - .clipShape(RoundedRectangle(cornerRadius: appIconCornerRadius, style: .continuous)) - .shadow(color: Color.black.opacity(0.35), radius: 6, x: 0, y: 4) - .offset(x: appIconOffset, y: appIconOffset) - .transition(.scale.combined(with: .opacity)) + ZStack(alignment: .bottomTrailing) { + albumArtImage(size: size, cornerRadius: cornerRadius) + if showAppIcon, let icon = lockScreenAppIcon { + icon + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: appIconSize, height: appIconSize) + + .shadow(color: Color.black.opacity(0.35), radius: 6, x: 0, y: 4) + .offset(x: appIconOffset, y: appIconOffset) + .transition(.scale.combined(with: .opacity)) + } } - } - .albumArtFlip(angle: musicManager.flipAngle) - .parallax3D(magnitude: 12, enableOverride: lockScreenParallaxEnabled, suspended: isParallaxSuspended) - .frame(width: size, height: size) - .background(albumArtBackground(cornerRadius: cornerRadius)) + .albumArtFlip(angle: musicManager.flipAngle) + .parallax3D(enableOverride: lockScreenParallaxEnabled, suspended: isParallaxSuspended) + .frame(width: size) + .background(albumArtBackground(cornerRadius: cornerRadius)) + .clipShape(RoundedRectangle(cornerRadius: musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? appIconCornerRadius/3 : appIconCornerRadius, style: .continuous)) } .buttonStyle(PlainButtonStyle()) .opacity(musicManager.isPlaying ? 1 : 0.4) @@ -1050,8 +1051,7 @@ struct LockScreenMusicPanel: View { Image(nsImage: musicManager.albumArt) .resizable() .aspectRatio(contentMode: .fit) - .frame(width: size, height: size) - .clipShape(RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)) + .clipShape(RoundedRectangle(cornerRadius: musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? cornerRadius/3 : cornerRadius)) } @ViewBuilder @@ -1082,7 +1082,7 @@ struct LockScreenMusicPanel: View { } private var appIconCornerRadius: CGFloat { - isExpanded ? 18 : 10 + isExpanded ? 18 : 12 } private var appIconOffset: CGFloat { diff --git a/DynamicIsland/components/MinimalisticMusicView.swift b/DynamicIsland/components/MinimalisticMusicView.swift index 23e364a..e830e19 100644 --- a/DynamicIsland/components/MinimalisticMusicView.swift +++ b/DynamicIsland/components/MinimalisticMusicView.swift @@ -63,6 +63,7 @@ struct MinimalisticMusicView: View { // Lyrics under the author name (same font size as author) if enableLyrics { lyricsLineView + .font(.system(size: 11, weight: .regular)) } } .frame(width: geo.size.width, height: geo.size.height, alignment: .center) @@ -93,9 +94,10 @@ struct MinimalisticMusicView: View { Image(nsImage: musicManager.albumArt) .resizable() .aspectRatio(contentMode: .fit) + .clipShape(RoundedRectangle(cornerRadius: musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? 4 : 12)) + ) .clipped() - .clipShape(RoundedRectangle(cornerRadius: 18)) // Dramatically increased corner radius for minimalistic mode .albumArtFlip(angle: musicManager.flipAngle) .frame(width: max(0, vm.effectiveClosedNotchHeight - 12), height: max(0, vm.effectiveClosedNotchHeight - 12)) } diff --git a/DynamicIsland/components/Notch/DynamicIslandHeader.swift b/DynamicIsland/components/Notch/DynamicIslandHeader.swift index 34e4610..c9eda7b 100644 --- a/DynamicIsland/components/Notch/DynamicIslandHeader.swift +++ b/DynamicIsland/components/Notch/DynamicIslandHeader.swift @@ -34,6 +34,7 @@ struct DynamicIslandHeader: View { @Default(.enableTimerFeature) var enableTimerFeature @Default(.timerDisplayMode) var timerDisplayMode @Default(.showClipboardIcon) var showClipboardIcon + @Default(.showColorPickerIcon) var showColorPickerIcon @Default(.clipboardDisplayMode) var clipboardDisplayMode var body: some View { @@ -50,6 +51,8 @@ struct DynamicIslandHeader: View { .blur(radius: vm.notchState == .closed ? 20 : 0) .animation(.smooth.delay(0.1), value: vm.notchState) .zIndex(2) + .padding(8) + } if vm.notchState == .open && !Defaults[.enableMinimalisticUI] { @@ -128,7 +131,7 @@ struct DynamicIslandHeader: View { } // ColorPicker button - if Defaults[.enableColorPickerFeature] { + if Defaults[.enableColorPickerFeature] && showColorPickerIcon{ Button(action: { switch Defaults[.colorPickerDisplayMode] { case .panel: @@ -293,7 +296,7 @@ private extension DynamicIslandHeader { Defaults[.settingsIconInNotch] && Defaults[.enableClipboardManager] && Defaults[.showClipboardIcon] - && Defaults[.enableColorPickerFeature] + && Defaults[.showColorPickerIcon] && Defaults[.enableTimerFeature] } } diff --git a/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift b/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift index 672b497..b17abc2 100644 --- a/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift +++ b/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift @@ -374,7 +374,7 @@ struct MinimalisticMusicPlayerView: View { private struct MinimalisticReminderEventListView: View { let reminders: [ReminderLiveActivityManager.ReminderEntry] - private let textFont = Font.system(size: 13, weight: .semibold) + private let textFont = Font.system(size: 13, weight: .regular) private let separatorSpacing: CGFloat = 10 var body: some View { @@ -1128,7 +1128,7 @@ struct MinimalisticAlbumArtView: View { .background( Image(nsImage: musicManager.albumArt) .resizable() - .aspectRatio(contentMode: .fit) + .scaledToFill() ) .clipped() .clipShape(RoundedRectangle(cornerRadius: 12)) @@ -1142,18 +1142,21 @@ struct MinimalisticAlbumArtView: View { Button { musicManager.openMusicApp() } label: { - Color.clear - .aspectRatio(1, contentMode: .fit) - .background( - Image(nsImage: musicManager.albumArt) - .resizable() - .aspectRatio(contentMode: .fit) - ) - .clipped() - .clipShape(RoundedRectangle(cornerRadius: 12)) - .matchedGeometryEffect(id: "albumArt", in: albumArtNamespace) - .albumArtFlip(angle: musicManager.flipAngle) - .parallax3D(magnitude: 12) + Color.clear + .aspectRatio(1, contentMode: .fit) + .background( + + Image(nsImage: musicManager.albumArt) + .resizable() + .aspectRatio(contentMode: .fit) + .clipShape(RoundedRectangle(cornerRadius: musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? 4 : 12)) + + + ) + .clipped() + .matchedGeometryEffect(id: "albumArt", in: albumArtNamespace) + .albumArtFlip(angle: musicManager.flipAngle) + .parallax3D() } .buttonStyle(PlainButtonStyle()) .opacity(musicManager.isPlaying ? 1 : 0.4) diff --git a/DynamicIsland/components/Notch/NotchHomeView.swift b/DynamicIsland/components/Notch/NotchHomeView.swift index 09d60e5..3041026 100644 --- a/DynamicIsland/components/Notch/NotchHomeView.swift +++ b/DynamicIsland/components/Notch/NotchHomeView.swift @@ -33,7 +33,6 @@ struct MusicPlayerView: View { var body: some View { HStack(alignment: .top, spacing: 12) { AlbumArtView(vm: vm, albumArtNamespace: albumArtNamespace) - .padding(.all, 5) MusicControlsView() .frame(maxWidth: .infinity, alignment: .leading) } @@ -62,14 +61,17 @@ struct AlbumArtView: View { Image(nsImage: musicManager.albumArt) .resizable() .aspectRatio(contentMode: .fit) + .clipShape( + RoundedRectangle( + cornerRadius: Defaults[.cornerRadiusScaling] + ? musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? MusicPlayerImageSizes.cornerRadiusInset.opened/3 : MusicPlayerImageSizes.cornerRadiusInset.opened + : musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? MusicPlayerImageSizes.cornerRadiusInset.closed/3 : MusicPlayerImageSizes.cornerRadiusInset.closed + + + ) + ) ) .clipped() - .clipShape( - RoundedRectangle( - cornerRadius: Defaults[.cornerRadiusScaling] - ? MusicPlayerImageSizes.cornerRadiusInset.opened - : MusicPlayerImageSizes.cornerRadiusInset.closed) - ) .scaleEffect(x: 1.3, y: 1.4) .rotationEffect(.degrees(92)) .blur(radius: 40) @@ -86,7 +88,9 @@ struct AlbumArtView: View { appIconOverlay } .albumArtFlip(angle: musicManager.flipAngle) - .parallax3D(magnitude: 12) + .parallax3D() + .padding(.bottom, -5) + } .buttonStyle(PlainButtonStyle()) .scaleEffect(musicManager.isPlaying ? 1 : 0.85) @@ -110,15 +114,18 @@ struct AlbumArtView: View { Image(nsImage: musicManager.albumArt) .resizable() .aspectRatio(contentMode: .fit) + .clipShape( + RoundedRectangle( + cornerRadius: Defaults[.cornerRadiusScaling] + ? musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? MusicPlayerImageSizes.cornerRadiusInset.opened/3 : MusicPlayerImageSizes.cornerRadiusInset.opened + : musicManager.albumArt.size.width/musicManager.albumArt.size.height > 1.0 ? MusicPlayerImageSizes.cornerRadiusInset.closed/3 : MusicPlayerImageSizes.cornerRadiusInset.closed + + + ) + ) // ensures that even the rectagular album cover is rounded just like the MacOS media player } .matchedGeometryEffect(id: "albumArt", in: albumArtNamespace) .clipped() - .clipShape( - RoundedRectangle( - cornerRadius: Defaults[.cornerRadiusScaling] - ? MusicPlayerImageSizes.cornerRadiusInset.opened - : MusicPlayerImageSizes.cornerRadiusInset.closed) - ) } @ViewBuilder @@ -126,8 +133,8 @@ struct AlbumArtView: View { if vm.notchState == .open && !musicManager.usingAppIconForArtwork { AppIcon(for: musicManager.bundleIdentifier ?? "com.apple.Music") .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 30, height: 30) + .scaledToFill() + .frame(width: 36, height: 36) .offset(x: 10, y: 10) .transition(.scale.combined(with: .opacity).animation(.bouncy.delay(0.3))) .zIndex(2) @@ -207,9 +214,9 @@ struct MusicControlsView: View { MarqueeText( lyricsBinding, - font: .headline, + font: .system(size: 12, weight: .regular), nsFont: .headline, - textColor: .white.opacity(0.8), + textColor: .white.opacity(0.7), minDuration: 0.35, frameWidth: width ) @@ -605,6 +612,7 @@ struct NotchHomeView: View { .combined(with: .blurReplace.animation(.smooth.speed(0.9))) .combined(with: .move(edge: .top))) .blur(radius: vm.notchState == .closed ? 30 : 0) + .padding(Defaults[.enableMinimalisticUI] ? 0 : 8) //Putting the main padding for home view here for consistency } private var minimalisticOverridePayload: ExtensionNotchExperiencePayload? { @@ -713,6 +721,7 @@ struct MusicSliderView: View { LiveStreamProgressIndicator(tint: sliderTint) .frame(maxWidth: .infinity) .frame(height: sliderFrameHeight) + case .inline: HStack(spacing: 10) { Spacer() @@ -720,6 +729,7 @@ struct MusicSliderView: View { LiveStreamProgressIndicator(tint: sliderTint) .frame(maxWidth: .infinity) .frame(height: sliderFrameHeight) + Spacer() .frame(width: 48) } @@ -748,10 +758,10 @@ struct MusicSliderView: View { ) } - private var sliderTint: Color { + private var sliderTint: Color {// switch Defaults[.sliderColor] { case .albumArt: - return Color(nsColor: color).ensureMinimumBrightness(factor: 0.8) + return Color(nsColor: color).ensureMinimumBrightness(factor: 0.6) case .accent: return .accentColor case .white: diff --git a/DynamicIsland/components/Settings/SettingsView.swift b/DynamicIsland/components/Settings/SettingsView.swift index 39692f5..58dfa77 100644 --- a/DynamicIsland/components/Settings/SettingsView.swift +++ b/DynamicIsland/components/Settings/SettingsView.swift @@ -2444,6 +2444,9 @@ struct Media: View { @Default(.lockScreenMusicAlbumParallaxEnabled) private var lockScreenMusicAlbumParallaxEnabled @Default(.showStandardMediaControls) private var showStandardMediaControls @Default(.autoHideInactiveNotchMediaPlayer) private var autoHideInactiveNotchMediaPlayer + @Default(.parallaxEffectIntensity) private var parallaxEffectIntensity + + @ObservedObject private var musicManager = MusicManager.shared private var isAppleMusicActive: Bool { @@ -2589,10 +2592,18 @@ struct Media: View { Text("Enable lyrics") } .settingsHighlight(id: highlightID("Enable lyrics")) - Defaults.Toggle(key: .enableParallaxEffect) { - Text("Enable album art parallax effect") + + //Parallax Effect Intensity to control how much parallax is wanted + Slider(value: $parallaxEffectIntensity, in: 0...12, step: 1.0) { + HStack { + Text("Parallax Effect Intensity") + Spacer() + Text("\(parallaxEffectIntensity, specifier: "%0.1f")") + .foregroundStyle(.secondary) + } } .settingsHighlight(id: highlightID("Enable album art parallax effect")) + Picker("Sneak Peek Style", selection: $sneakPeekStyles){ ForEach(SneakPeekStyle.allCases) { style in Text(style.rawValue).tag(style) diff --git a/DynamicIsland/components/Tabs/TabButton.swift b/DynamicIsland/components/Tabs/TabButton.swift index c6f59a2..903bfa4 100644 --- a/DynamicIsland/components/Tabs/TabButton.swift +++ b/DynamicIsland/components/Tabs/TabButton.swift @@ -31,7 +31,6 @@ struct TabButton: View { var body: some View { Button(action: onClick) { Image(systemName: icon) - .padding(.horizontal, 15) .contentShape(Capsule()) } .buttonStyle(PlainButtonStyle()) diff --git a/DynamicIsland/components/Tabs/TabSelectionView.swift b/DynamicIsland/components/Tabs/TabSelectionView.swift index 33939fc..77eee5d 100644 --- a/DynamicIsland/components/Tabs/TabSelectionView.swift +++ b/DynamicIsland/components/Tabs/TabSelectionView.swift @@ -109,7 +109,7 @@ struct TabSelectionView: View { return tabsArray } var body: some View { - HStack(spacing: 0) { + HStack(spacing: 24) { ForEach(Array(tabs.enumerated()), id: \.element.id) { idx, tab in let isSelected = isSelected(tab) let activeAccent = tab.accentColor ?? .white diff --git a/DynamicIsland/extensions/View+Parallax3D.swift b/DynamicIsland/extensions/View+Parallax3D.swift index 81c2752..35d2759 100644 --- a/DynamicIsland/extensions/View+Parallax3D.swift +++ b/DynamicIsland/extensions/View+Parallax3D.swift @@ -22,17 +22,16 @@ import AppKit import Defaults struct ParallaxMotionModifier: ViewModifier { - var magnitude: Double var enableOverride: Bool? var isSuspended: Bool - @Default(.enableParallaxEffect) var enableParallaxEffect + @Default(.parallaxEffectIntensity) var parallaxEffectIntensity @State private var offset: CGSize = .zero @State private var isHovering = false @State private var viewSize: CGSize = .zero func body(content: Content) -> some View { - if isSuspended || !(enableOverride ?? enableParallaxEffect) { + if isSuspended || !(enableOverride ?? (parallaxEffectIntensity > 0.0)) { content } else { content @@ -69,11 +68,11 @@ struct ParallaxMotionModifier: ViewModifier { } } .rotation3DEffect( - .degrees(offset.height * magnitude), // Y movement rotates around X axis + .degrees(offset.height * parallaxEffectIntensity), // Y movement rotates around X axis axis: (x: 1, y: 0, z: 0) ) .rotation3DEffect( - .degrees(offset.width * -magnitude), // X movement rotates around Y axis (inverted to look naturally) + .degrees(offset.width * -parallaxEffectIntensity), // X movement rotates around Y axis (inverted to look naturally) axis: (x: 0, y: 1, z: 0) ) .scaleEffect(isHovering ? 1.02 : 1.0) // Subtle scale up on hover @@ -83,10 +82,9 @@ struct ParallaxMotionModifier: ViewModifier { extension View { func parallax3D( - magnitude: Double = 10, enableOverride: Bool? = nil, suspended: Bool = false ) -> some View { - modifier(ParallaxMotionModifier(magnitude: magnitude, enableOverride: enableOverride, isSuspended: suspended)) + modifier(ParallaxMotionModifier(enableOverride: enableOverride, isSuspended: suspended)) } } diff --git a/DynamicIsland/models/Constants.swift b/DynamicIsland/models/Constants.swift index 0ffefa5..77e53b8 100644 --- a/DynamicIsland/models/Constants.swift +++ b/DynamicIsland/models/Constants.swift @@ -779,7 +779,7 @@ extension Defaults.Keys { static let sneakPeekStyles = Key("sneakPeekStyles", default: .standard) static let showSneakPeekOnTrackChange = Key("showSneakPeekOnTrackChange", default: true) static let enableFullscreenMediaDetection = Key("enableFullscreenMediaDetection", default: true) - static let enableParallaxEffect = Key("enableParallaxEffect", default: true) + static let parallaxEffectIntensity = Key("parallaxEffectIntensity", default: 6.0) static let waitInterval = Key("waitInterval", default: 3) static let showShuffleAndRepeat = Key("showShuffleAndRepeat", default: true) static let showMediaOutputControl = Key("showMediaOutputControl", default: true)