Intervals
Intervals you build on steppers and run full screen in the color of each phase, with the whole workout as a strip you move through.
An interval timer: pick a format (Tabata, EMOM, a pyramid, a ladder or your own), set rounds, work and rest on steppers and watch the workout's rhythm redraw. Start fills the screen with the phase's color: a giant countdown, the move and what comes next, a level that rises through each interval and the rhythm strip along the bottom lighting up as you go, with a three-two-one count, haptics and count-in tones you can switch on. A training session runs in it too, counted move by move and set by set.
$199 once, every piece included. See how installing works · Sign in
What's included
SwiftUI source you own, built on Apple frameworks only.
- Formats you shape on steppers, with the rhythm redrawing as you go
- A full-screen session in the color of each phase
- A level that rises through every interval, and the whole workout as a strip
- A three-two-one count with haptics, and count-in tones you can switch on
- A pure
IntervalClockyou can test, driving the whole session
Health and Fitness (brief). Your agent builds around this screen in the same design.
Fitness App (template)
Implementation notes
How it behaves, what it handles, and the decisions behind it.
The builder opens on a row of formats: Tabata, EMOM, a pyramid, a ladder and your own, each chip carrying a tiny strip of its rhythm in the format's block, and the chosen one turning into that block. Under it the workout's total sits as a giant light numeral with its rhythm in words, "8 rounds · 20 s work · 10 s rest", and then the workout itself as a large rhythm strip: work as tall bars in the block, rest as short pale ones, every bar as wide as it is long and 2pt from the next. Three stepper tiles set rounds, work and rest; hold minus or plus and it repeats with a tick per step while the strip redraws with a spring and the total rolls. Start fills the screen with the phase's color. A lighter level rises from the bottom through each interval, the phase, a giant countdown, the move and what comes next sit left aligned in the middle, and the session runs along the bottom as the same strip, the bars behind you in solid ink and the current one filling. Work, rest and "Get ready" each take their own block, the last three seconds pulse the numeral with a light haptic each, and every change lands a firmer one.
Notes
IntervalTimer(plans:)is the builder with the session built in: Start presentsIntervalSessionfull screen. PassonStartto present it yourself,onSaveto keep edits (Save appears beside Start once a format is changed),onFinishfor the summary andopenedto select a format on appear.- A format is an
IntervalPlan: work durations (one value for most formats, a run for a pyramid or a ladder), rest, rounds, a "Get ready" count, a cool-down and move names.IntervalPlan.formatsships Tabata, EMOM, Pyramid, Ladder and Custom, andIntervalPlan.steps(id:name:steps:)builds one from explicit steps, such as a training session's sets. IntervalClock(plan:)is pure:state(at:)returns the phase, the round, the time left in the phase and the overall progress for any second, so the session is easy to test.IntervalRunholds elapsed time and pause; give one run toIntervalSession(run:)and to a compact player and both follow the same clock.RhythmStripdraws any workout fromRhythmBeats (IntervalPlan.beats,IntervalClock.beats). In a plan of steps, a rest between two different moves is a changeover and sits on the floor, so each move's sets read as one group. Passprogressto play it.IntervalFieldmaps each phase to a block in one place: work in the plan's block, rest in a calm one, "Get ready" and the cool-down in the deepest. Every family paints its own fields, with the ink computed for each block.- In the session, pause with the middle button, skip back and forward beside it, and hold the close button to end, so a stray tap never stops a workout. The screen stays awake while it runs, and
onFinishreceives anIntervalSummarywith the total, the work time, the rounds and whether it ran to the end. When it ends, the same field settles into Done with the total and the rounds. - Haptics are on by default: a light tap on each of the last three seconds of a phase and a firmer one as the next begins.
.intervalHaptics(false)turns them off for everything inside, and.intervalSounds(true)adds count-in tones, synthesized on the fly so there are no audio files to ship. Unless your app has set up its own audio session, the tones mix with the person's music and follow the silent switch. A run that plays somewhere else cues with.intervalCues(for: run). - VoiceOver reads the phase, the move, the round and the seconds left. The session is adjustable, so swiping up or down skips, and a magic tap pauses. The stepper tiles are adjustable too, and the format chips report their rhythm.
- Reduce Motion keeps the heat still instead of swelling, steps the rising level once a second and turns the countdown into a cross-fade. The strip and the totals still update. Reduce Transparency leaves Pearl's haze out of the field, so the numerals sit on flat color.
- In Pearl the heat behind the countdown is the haze, blooming in white light so it never greys the field. Other families let their own motif swell in the same rhythm: thin rings in Neon, a half disc and a dot matrix in Graphic.
IntervalTimerExampleat the end ofIntervalTimer.swiftis the screen in the preview, the Timer tab of a native four-tabTabView. Copy it as a starting point.
Keep building
Pieces that work well next to this one.