Skip to content

Take the click's tempo band, default and metre presets from the core #2225

Closed

Description

@jonyardley

What you would notice

The click's band (40 to 208, default 96, scaled by beat unit), its pattern and metre presets, and the reflection stepper's clamp all live in Swift, while the core accepts any tempo from 1 to 500. A tempo recorded outside the click's band is silently clamped when the reflection sheet opens.

Why it matters

Found by the Swift shell rules review on #2223. The Android app (#2220) would otherwise reimplement this rule, and the two copies would drift. Severity for the port: High.

What to do

Put the band, default, presets and the groupings per beat count in domain/metre.rs, exposed through LimitsView; the click and the stepper read them. Click seeding (default 4/4, the item's own tempo, a metre change resetting beats, the last beat staying on) moves with them.

Done looks like

  • The click and the reflection stepper show the same band as before, read from the view model.
  • No tempo constant remains in TempoScale.swift or ClickPattern.swift.

Where it lives

ios/Intrada/Core/TempoScale.swift, ClickPattern.swift, ClickController.swift:38-109, Views/Screens/ReflectionSheet.swift:15-22, Views/Components/ClickSheet.swift; crates/intrada-core/src/domain/metre.rs.

Activity

  1. added
    architectureArchitecture, technical debt, infrastructure
    iosiOS-specific work (native SwiftUI shell on Crux — see specs/native-ios.md)
    on Oct 2, 2026
  2. jonyardley commented on Oct 2, 2026

    @jonyardley
    OwnerAuthor

    Claimed: branch click-limits-2225. Epic: #2220.

  3. added
    in-flightClaimed: a branch or PR is actively working this
    on Oct 2, 2026
  4. jonyardley commented on Oct 2, 2026

    @jonyardley
    OwnerAuthor

    Done looks like: the click and the reflection stepper offer the same tempo range, metres, groupings and patterns as today, read from the view model; TempoScale.swift and ClickPattern.swift are gone.

    Time budget: one session, two PRs.

    Decisions taken: the band, step, default, metre presets, groupings and offered patterns live in domain/metre.rs and reach the shell through LimitsView, one band per beat unit derived with Metre::displayed_bpm (rejected: the shell scaling by unit, which Android would repeat). The click's starting tempo, whether it is the item's own, and a starting metre defaulting to 4/4 join ActiveSessionView. The last-beat-stays-on tap guard stays in Swift: the core can only rule per tap through an event, which would move click state into the core, and validation already refuses an empty mask at hand-off. Pattern titles stay in Swift, keyed by the core's preset.

    Files: metre.rs, practice_defaults.rs (mask reuse), model.rs, view/session.rs, both generated bindings; then ClickController, ClickSheet, ClickControl, TempoStepper, ReflectionSheet, PracticeDefaultsSection, their tests; specs/practice-instruments.md gains a section.

    Tests: Rust table tests from musician inputs (7/8 at 168, 2/2 at 20, nine beats grouped); deleting the unit scaling breaks the 6/8 ceiling of 416.

    Rabbit holes: the generated type name colliding with the Swift ClickPattern while both exist; the core type takes a different name.

    Out of scope: drag feel, the click engine, the crash-recovery blob, Android screens.

    Routing: epic #2220; bridge shape, so sensitive, core PR first then screens, this session.

  5. removed
    in-flightClaimed: a branch or PR is actively working this
    on Oct 3, 2026
  6. jonyardley commented on Oct 3, 2026

    @jonyardley
    OwnerAuthor

    Reopened: #2293 closed this by accident (its body said "the follow-up that closes #2225"). The iOS screens half is still to do and its PR closes this.

  7. jonyardley commented on Oct 3, 2026

    @jonyardley
    OwnerAuthor

    Closing again: the core half shipped in #2293, and the iOS screens half moved to #2302 so it can be claimed and closed by its own PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureArchitecture, technical debt, infrastructurehorizon:nextNext — 4–12 weeksiosiOS-specific work (native SwiftUI shell on Crux — see specs/native-ios.md)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions