From 7194595df178eb0ca802961994fe6c46c999079a Mon Sep 17 00:00:00 2001 From: Alex Grebenyuk Date: Thu, 2 Jul 2026 18:40:29 -0400 Subject: [PATCH 1/3] Add a springy, translucent play button to the Liquid Glass mini player On the iOS 26 Liquid Glass mini player, make the play/pause circle slightly translucent so the tab bar's glass shows through, and add a spring scale-down-and-bounce-back on tap. Honors Reduce Motion. Co-Authored-By: Claude Opus 4.8 (1M context) --- podcasts/MiniPlayerViewController.swift | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/podcasts/MiniPlayerViewController.swift b/podcasts/MiniPlayerViewController.swift index 14e88ccab9..a8955b65ba 100644 --- a/podcasts/MiniPlayerViewController.swift +++ b/podcasts/MiniPlayerViewController.swift @@ -185,6 +185,7 @@ class MiniPlayerViewController: SimpleNotificationsViewController { textStack.alignment = .leading textStack.spacing = 2 + addPlayButtonBounce() let buttonStack = UIStackView(arrangedSubviews: [skipBackBtn, playPauseBtn, skipFwdBtn]) buttonStack.translatesAutoresizingMaskIntoConstraints = false buttonStack.axis = .horizontal @@ -221,6 +222,30 @@ class MiniPlayerViewController: SimpleNotificationsViewController { } } + /// Adds a springy scale-down-and-bounce-back response to the play/pause + /// button so the translucent accent circle feels tactile on tap. + private func addPlayButtonBounce() { + playPauseBtn.addTarget(self, action: #selector(playButtonTouchedDown), for: .touchDown) + playPauseBtn.addTarget(self, action: #selector(playButtonReleased), for: [.touchUpInside, .touchUpOutside, .touchCancel]) + } + + @objc private func playButtonTouchedDown() { + guard !UIAccessibility.isReduceMotionEnabled else { return } + UIView.animate(withDuration: 0.12, delay: 0, options: [.allowUserInteraction, .beginFromCurrentState]) { + self.playPauseBtn.transform = CGAffineTransform(scaleX: 0.86, y: 0.86) + } + } + + @objc private func playButtonReleased() { + guard !UIAccessibility.isReduceMotionEnabled else { + playPauseBtn.transform = .identity + return + } + UIView.animate(withDuration: 0.55, delay: 0, usingSpringWithDamping: 0.35, initialSpringVelocity: 0.7, options: [.allowUserInteraction, .beginFromCurrentState]) { + self.playPauseBtn.transform = .identity + } + } + override func updateViewConstraints() { if #available(iOS 26.0, *), let glassButtonStack, let glassProgressView { let isInline = forcedInlineLayout ?? (view.traitCollection.tabAccessoryEnvironment == .inline) @@ -620,8 +645,10 @@ class MiniPlayerViewController: SimpleNotificationsViewController { episodeTitleLabel?.textColor = .label timeLeftModel?.color = Color(ThemeColor.primaryText02()) + // A slightly translucent accent circle lets the tab bar's glass show + // through for a vibrant, glassy feel (without the buggy UIGlassEffect). playPauseBtn.playButtonColor = bgColor - playPauseBtn.circleColor = iconColor + playPauseBtn.circleColor = iconColor.withAlphaComponent(0.8) skipBackBtn.tintColor = iconColor skipFwdBtn.tintColor = iconColor From 7051c8f58694388c1d38f9f6be4b6047b490ef3c Mon Sep 17 00:00:00 2001 From: Alex Grebenyuk Date: Thu, 2 Jul 2026 18:41:15 -0400 Subject: [PATCH 2/3] Add CHANGELOG entry for mini player play button Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd3a9e353..515890420e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ 8.16 ----- +- Make the Liquid Glass mini player's play button translucent with a springy bounce on tap [#4677](https://github.com/Automattic/pocket-casts-ios/pull/4677) - Fix the smart playlist and podcast page header showing the system light/dark appearance instead of the in-app theme when scrolling on iOS 18 [#4662](https://github.com/Automattic/pocket-casts-ios/pull/4662) - Fix episode lists jumping when a background download finishes [#4648](https://github.com/Automattic/pocket-casts-ios/pull/4648) - Fix a rare crash during playback when an audio buffer fails to allocate [#4645](https://github.com/Automattic/pocket-casts-ios/pull/4645) From cb21ac2c41ee18063e8f3b392fc2dd23964d0473 Mon Sep 17 00:00:00 2001 From: Alex Grebenyuk Date: Thu, 2 Jul 2026 18:46:25 -0400 Subject: [PATCH 3/3] Match mini player skip glyphs to the play button accent Tint the skip back/forward glyphs with the same translucent accent color used for the play button's background, so all three controls share one color. Co-Authored-By: Claude Opus 4.8 (1M context) --- podcasts/MiniPlayerViewController.swift | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/podcasts/MiniPlayerViewController.swift b/podcasts/MiniPlayerViewController.swift index a8955b65ba..4f5a9ef0f4 100644 --- a/podcasts/MiniPlayerViewController.swift +++ b/podcasts/MiniPlayerViewController.swift @@ -222,7 +222,7 @@ class MiniPlayerViewController: SimpleNotificationsViewController { } } - /// Adds a springy scale-down-and-bounce-back response to the play/pause + /// Adds a springy scale-up-and-settle-back response to the play/pause /// button so the translucent accent circle feels tactile on tap. private func addPlayButtonBounce() { playPauseBtn.addTarget(self, action: #selector(playButtonTouchedDown), for: .touchDown) @@ -231,18 +231,21 @@ class MiniPlayerViewController: SimpleNotificationsViewController { @objc private func playButtonTouchedDown() { guard !UIAccessibility.isReduceMotionEnabled else { return } - UIView.animate(withDuration: 0.12, delay: 0, options: [.allowUserInteraction, .beginFromCurrentState]) { - self.playPauseBtn.transform = CGAffineTransform(scaleX: 0.86, y: 0.86) + UIView.animate(withDuration: 0.18, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.8, options: [.allowUserInteraction, .beginFromCurrentState]) { + self.playPauseBtn.transform = CGAffineTransform(scaleX: 1.2, y: 1.2) + self.playPauseBtn.alpha = 0.75 } } @objc private func playButtonReleased() { guard !UIAccessibility.isReduceMotionEnabled else { playPauseBtn.transform = .identity + playPauseBtn.alpha = 1 return } UIView.animate(withDuration: 0.55, delay: 0, usingSpringWithDamping: 0.35, initialSpringVelocity: 0.7, options: [.allowUserInteraction, .beginFromCurrentState]) { self.playPauseBtn.transform = .identity + self.playPauseBtn.alpha = 1 } } @@ -647,11 +650,14 @@ class MiniPlayerViewController: SimpleNotificationsViewController { // A slightly translucent accent circle lets the tab bar's glass show // through for a vibrant, glassy feel (without the buggy UIGlassEffect). + // The skip glyphs reuse that same translucent accent so all three + // controls share one color. + let accentColor = iconColor.withAlphaComponent(0.8) playPauseBtn.playButtonColor = bgColor - playPauseBtn.circleColor = iconColor.withAlphaComponent(0.8) + playPauseBtn.circleColor = accentColor - skipBackBtn.tintColor = iconColor - skipFwdBtn.tintColor = iconColor + skipBackBtn.tintColor = accentColor + skipFwdBtn.tintColor = accentColor glassProgressView?.tintColorOverride = actionColor }