feat(fitness): support repeat groups in interval training templates

Allow users to nest steps inside a repeat group (e.g. "5×: 30s sprint,
60s recovery") when building GPS interval templates. Groups are tagged
{ type: 'group', repeat, steps } alongside flat { type: 'step' } entries
and capped at one nesting level. Entries are expanded into a flat list
before handing off to the native Android TTS/interval service, so the
runtime state machine is unchanged.
This commit is contained in:
2026-04-13 09:17:38 +02:00
parent 0ef8ee38c5
commit 7c3e90933d
8 changed files with 398 additions and 118 deletions
+28
View File
@@ -15,11 +15,39 @@ export interface GpsPoint {
}
export interface IntervalStep {
type?: 'step';
label: string;
durationType: 'distance' | 'time';
durationValue: number; // meters (distance) or seconds (time)
}
export interface IntervalGroup {
type: 'group';
repeat: number;
steps: IntervalStep[];
}
export type IntervalEntry = IntervalStep | IntervalGroup;
/** Expand groups (repeat × steps) into a flat step list for the native bridge. */
export function flattenIntervals(entries: IntervalEntry[]): IntervalStep[] {
const out: IntervalStep[] = [];
for (const e of entries) {
if ((e as IntervalGroup).type === 'group') {
const g = e as IntervalGroup;
for (let i = 0; i < g.repeat; i++) {
for (const s of g.steps) {
out.push({ label: s.label, durationType: s.durationType, durationValue: s.durationValue });
}
}
} else {
const s = e as IntervalStep;
out.push({ label: s.label, durationType: s.durationType, durationValue: s.durationValue });
}
}
return out;
}
export interface VoiceGuidanceConfig {
enabled: boolean;
triggerType: 'distance' | 'time';