Skip to content
This repository was archived by the owner on Jul 7, 2026. It is now read-only.

Replace system playback menus with Tuner panels#69

Merged
zachyzissou merged 2 commits into
mainfrom
codex/tuner-inline-action-panels
Apr 30, 2026
Merged

Replace system playback menus with Tuner panels#69
zachyzissou merged 2 commits into
mainfrom
codex/tuner-inline-action-panels

Conversation

@zachyzissou

Copy link
Copy Markdown
Owner

Summary

  • Replace the episode download Menu with a direct Tuner-styled primary action
  • Replace player speed and sleep timer Menus with inline Tuner option grids
  • Replace the settings default playback rate Menu with an inline Tuner rate picker

Verification

  • xcodebuild build -project OffScript.xcodeproj -scheme OffScript -destination 'platform=iOS Simulator,OS=latest,name=iPhone 17 Pro'
  • xcodebuild test -project OffScript.xcodeproj -scheme OffScript -destination 'platform=iOS Simulator,OS=latest,name=iPhone 17 Pro' -only-testing:OffScriptTests
  • Xcode MCP BuildProject on windowtab1

Notes

Copilot AI review requested due to automatic review settings April 30, 2026 08:03
@zachyzissou zachyzissou force-pushed the codex/tuner-inline-action-panels branch from 0e8b35b to f24c055 Compare April 30, 2026 08:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces several system Menu-based playback controls with inline Tuner-styled panels/pickers, aligning playback-related UI with the app’s “instrument cluster” design language.

Changes:

  • Replace Settings “Default playback rate” menu with an expandable inline rate picker.
  • Replace Player speed and sleep timer menus with inline option grids/panels.
  • Replace the episode download menu with a single primary action button based on download state.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
OffScript/SettingsView.swift Adds an expandable inline default playback-rate picker UI.
OffScript/PlayerView.swift Converts speed + sleep timer menus into inline Tuner pickers and adds expansion state.
OffScript/DownloadButton.swift Replaces the download action menu with a state-driven single-tap primary action.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +30 to +38
private func performPrimaryDownloadAction() {
switch episode.downloadState {
case .notDownloaded, .failed:
downloadService.startDownload(for: episode)
case .downloading, .queued:
downloadService.cancelDownload(for: episode)
case .downloaded:
downloadService.deleteDownload(for: episode)
}

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When downloadState is .downloaded, a single tap now immediately deletes the local file (previously exposed as a destructive menu action). Consider adding a confirmation step (e.g. confirmationDialog) or requiring an explicit secondary action for delete to avoid accidental data removal.

Copilot uses AI. Check for mistakes.
Comment on lines +203 to +216
Button {
withAnimation(.easeInOut(duration: 0.16)) {
isDefaultRatePickerExpanded.toggle()
}
} label: {
HStack(spacing: 6) {
TunerLabel(
text: String(format: "%.2g×", currentDefaultRate),
color: .offscriptSignalYellow,
size: 11
)
Image(systemName: isDefaultRatePickerExpanded ? "chevron.up" : "chevron.down")
.font(.system(size: 10, weight: .bold))
.foregroundStyle(Color.offscriptSignalYellow)

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The playback-rate toggle button relies on its visual label (current rate + chevron) but has no explicit accessibility label/value/hint. For VoiceOver this will be read without context; consider adding an accessibilityLabel like “Default playback rate”, an accessibilityValue with the current rate, and a hint indicating it expands/collapses the picker.

Copilot uses AI. Check for mistakes.
Comment thread OffScript/PlayerView.swift Outdated
Comment on lines +487 to +491
private func tunerRatePicker(
rates: [Float],
selectedRate: Float,
onSelect: @escaping (Float) -> Void
) -> some View {

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tunerRatePicker is now implemented separately in both SettingsView and PlayerView with very similar layout/styling. This duplication makes future tweaks (sizes, colors, accessibility) easy to drift; consider extracting a shared TunerRatePicker view/helper (e.g., in a UI components file) and reusing it in both places.

Copilot uses AI. Check for mistakes.
Comment thread OffScript/PlayerView.swift Outdated
.background(isSelected ? Color.offscriptSignalYellow : Color.clear)
.overlay(Rectangle().stroke(isSelected ? Color.offscriptSignalYellow : Color.offscriptHairline, lineWidth: 1))
}
.buttonStyle(.plain)

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new inline speed buttons don’t provide per-option accessibility labels/selected traits. SettingsView’s rate picker adds an explicit accessibilityLabel per rate, but PlayerView’s picker does not; adding labels (e.g. “Set playback speed to …”) and .isSelected traits for the current rate would make this control much clearer to VoiceOver users.

Suggested change
.buttonStyle(.plain)
.buttonStyle(.plain)
.accessibilityElement(children: .ignore)
.accessibilityLabel("Set playback speed to \(String(format: "%.2g", rate))x")
.accessibilityAddTraits(isSelected ? .isSelected : [])
.accessibilityRemoveTraits(isSelected ? [] : .isSelected)

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 28
@@ -40,6 +27,17 @@ struct DownloadButton: View {
.accessibilityLabel(downloadAccessibilityLabel)
}

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This button now performs different actions depending on download state (start/cancel/delete), but the accessibility label reads as a status in several cases (e.g. “is downloaded”, “is queued for download”). Add an accessibilityHint/value that describes what activating the control will do in each state (e.g. “Double-tap to remove download” when downloaded, “Double-tap to cancel” when downloading) so the action is not surprising for assistive-tech users.

Copilot uses AI. Check for mistakes.
@zachyzissou

Copy link
Copy Markdown
Owner Author

Addressed Copilot review feedback in 10916dc:\n\n- Added shared TunerRatePicker and reused it from Player + Settings.\n- Added explicit accessibility labels/values/hints and selected traits for the inline rate options.\n- Changed downloaded episodes to require a second tap to remove the local file, using an armed REMOVE? state instead of restoring system confirmation chrome.\n\nVerification after the fixes:\n- git diff --check\n- xcodebuild build -project OffScript.xcodeproj -scheme OffScript -destination 'platform=iOS Simulator,OS=latest,name=iPhone 17 Pro'\n- xcodebuild test -project OffScript.xcodeproj -scheme OffScript -destination 'platform=iOS Simulator,OS=latest,name=iPhone 17 Pro' -only-testing:OffScriptTests

@zachyzissou zachyzissou merged commit d1afa3c into main Apr 30, 2026
@zachyzissou zachyzissou deleted the codex/tuner-inline-action-panels branch April 30, 2026 08:08
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants