@adminide-stack/yantra-mobile 12.0.142-alpha.0 → 12.0.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,116 @@
1
+ const WATER_FRACTION_OF_FFM = 0.72;
2
+ const BONE_FRACTION_OF_FFM = 0.0497;
3
+ const round1 = (n) => Math.round(n * 10) / 10;
4
+ const round2 = (n) => Math.round(n * 100) / 100;
5
+ function computeBodyComposition(input) {
6
+ const {
7
+ weightKg,
8
+ bodyFatPct,
9
+ heightCm,
10
+ age
11
+ } = input;
12
+ const male = input.sex === "male";
13
+ const heightM = heightCm / 100;
14
+ const bmi = heightM > 0 ? weightKg / (heightM * heightM) : 0;
15
+ const fat = Math.max(0, Math.min(75, bodyFatPct)) / 100;
16
+ const fatMassKg = weightKg * fat;
17
+ const leanMassKg = weightKg - fatMassKg;
18
+ const boneMassKg = leanMassKg * BONE_FRACTION_OF_FFM;
19
+ const muscleMassKg = leanMassKg - boneMassKg;
20
+ const bodyWaterKg = leanMassKg * WATER_FRACTION_OF_FFM;
21
+ const proteinKg = Math.max(0, leanMassKg - bodyWaterKg - boneMassKg);
22
+ let skeletalMuscleMassKg;
23
+ if (input.impedanceOhm && input.impedanceOhm > 0) {
24
+ const sexTerm = male ? 3.825 : 0;
25
+ skeletalMuscleMassKg = 0.401 * (heightCm * heightCm) / input.impedanceOhm + sexTerm - 0.071 * age + 5.102;
26
+ skeletalMuscleMassKg = Math.max(0, Math.min(muscleMassKg, skeletalMuscleMassKg));
27
+ } else {
28
+ skeletalMuscleMassKg = muscleMassKg * (male ? 0.68 : 0.62);
29
+ }
30
+ const bmr = Math.round(370 + 21.6 * leanMassKg);
31
+ const metabolicAge = estimateMetabolicAge(bmr, heightCm, male, age);
32
+ const visceralFat = Math.max(1, Math.min(59, Math.round(fatMassKg * (male ? 1 : 0.85) / 2.2 + age / 12 - 3)));
33
+ const subcutaneousFatPct = Math.max(0, bodyFatPct - visceralFat * 0.33);
34
+ const pct = (kg) => weightKg > 0 ? kg / weightKg * 100 : 0;
35
+ return {
36
+ bmi: round1(bmi),
37
+ fatMassKg: round2(fatMassKg),
38
+ leanMassKg: round2(leanMassKg),
39
+ muscleMassKg: round2(muscleMassKg),
40
+ musclePct: round1(pct(muscleMassKg)),
41
+ skeletalMuscleMassKg: round2(skeletalMuscleMassKg),
42
+ skeletalMusclePct: round1(pct(skeletalMuscleMassKg)),
43
+ boneMassKg: round2(boneMassKg),
44
+ bonePct: round1(pct(boneMassKg)),
45
+ bodyWaterKg: round2(bodyWaterKg),
46
+ bodyWaterPct: round1(pct(bodyWaterKg)),
47
+ proteinKg: round2(proteinKg),
48
+ proteinPct: round1(pct(proteinKg)),
49
+ bmr,
50
+ metabolicAge,
51
+ visceralFat,
52
+ subcutaneousFatPct: round1(subcutaneousFatPct)
53
+ };
54
+ }
55
+ function compositionRows(c, units = "metric") {
56
+ const kg = (v) => units === "imperial" ? `${Math.round(v / 0.45359237 * 10) / 10} lb` : `${v} kg`;
57
+ const pct = (v) => `${v}%`;
58
+ return [{
59
+ label: "BMI",
60
+ value: String(c.bmi)
61
+ }, {
62
+ label: "Fat mass",
63
+ value: kg(c.fatMassKg)
64
+ }, {
65
+ label: "Fat-free mass",
66
+ value: kg(c.leanMassKg)
67
+ }, {
68
+ label: "Muscle mass",
69
+ value: kg(c.muscleMassKg)
70
+ }, {
71
+ label: "Muscle",
72
+ value: pct(c.musclePct)
73
+ }, {
74
+ label: "Skeletal muscle",
75
+ value: kg(c.skeletalMuscleMassKg)
76
+ }, {
77
+ label: "Bone mass",
78
+ value: kg(c.boneMassKg)
79
+ }, {
80
+ label: "Body water",
81
+ value: pct(c.bodyWaterPct)
82
+ }, {
83
+ label: "Protein",
84
+ value: pct(c.proteinPct)
85
+ }, {
86
+ label: "BMR",
87
+ value: `${c.bmr} kcal`
88
+ }, {
89
+ label: "Metabolic age",
90
+ value: `${c.metabolicAge} yrs`
91
+ }, {
92
+ label: "Visceral fat",
93
+ value: String(c.visceralFat)
94
+ }, {
95
+ label: "Subcutaneous fat",
96
+ value: pct(c.subcutaneousFatPct)
97
+ }];
98
+ }
99
+ function estimateMetabolicAge(bmr, heightCm, male, age) {
100
+ const ffmAt = (a) => {
101
+ const base = male ? 0.407 * heightCm - 15 : 0.357 * heightCm - 13;
102
+ const decline = a > 25 ? (a - 25) * 0.1 : 0;
103
+ return Math.max(20, base - decline);
104
+ };
105
+ const bmrAt = (a) => 370 + 21.6 * ffmAt(a);
106
+ let best = age;
107
+ let bestDiff = Infinity;
108
+ for (let a = 18; a <= 80; a++) {
109
+ const diff = Math.abs(bmrAt(a) - bmr);
110
+ if (diff < bestDiff) {
111
+ bestDiff = diff;
112
+ best = a;
113
+ }
114
+ }
115
+ return best;
116
+ }export{compositionRows,computeBodyComposition};//# sourceMappingURL=bodyComposition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bodyComposition.js","sources":["../../../src/features/devices/bodyComposition.ts"],"sourcesContent":["/**\n * Full body composition from a scale reading, using established published\n * formulas (not any vendor's proprietary coefficients).\n *\n * A body-fat scale measures weight and bioelectrical impedance and, from the\n * person's height/age/sex, estimates body-fat percentage. Everything else a\n * scale app shows (fat-free mass, muscle, bone, body water, protein, BMR,\n * metabolic age, visceral/subcutaneous fat) is derived from weight and body\n * fat with standard equations:\n *\n * - Fat mass / fat-free mass: definitional.\n * - Total body water: FFM is ~72% water (the standard hydration constant).\n * - Bone mineral: a small, roughly fixed fraction of fat-free mass.\n * - Muscle mass = fat-free mass minus bone mineral; protein is the dry\n * non-mineral remainder.\n * - BMR: Katch-McArdle (370 + 21.6 x FFM), which depends only on lean mass.\n * - Skeletal muscle: Janssen's impedance equation when impedance is known.\n *\n * These reproduce a RENPHO/QN scale's derived numbers closely because the scale\n * uses the same public science; the only vendor-specific step is the body-fat\n * estimate, which the device sends directly, so Yantra does not recompute it.\n */\n\nexport interface BodyCompositionInput {\n weightKg: number;\n bodyFatPct: number;\n heightCm: number;\n age: number;\n sex: 'male' | 'female' | 'unspecified';\n /** Whole-body impedance in ohms, when the scale reported it (for skeletal muscle). */\n impedanceOhm?: number;\n}\n\nexport interface BodyComposition {\n bmi: number;\n fatMassKg: number;\n /** Fat-free (lean) mass. */\n leanMassKg: number;\n muscleMassKg: number;\n musclePct: number;\n skeletalMuscleMassKg: number;\n skeletalMusclePct: number;\n boneMassKg: number;\n bonePct: number;\n bodyWaterKg: number;\n bodyWaterPct: number;\n proteinKg: number;\n proteinPct: number;\n /** Basal metabolic rate, kcal/day. */\n bmr: number;\n metabolicAge: number;\n /** Visceral fat rating (unitless, like the scale's 1-59 scale). */\n visceralFat: number;\n subcutaneousFatPct: number;\n}\n\n/** Fraction of fat-free mass that is water (standard hydration constant). */\nconst WATER_FRACTION_OF_FFM = 0.72;\n/** Fraction of fat-free mass that is bone mineral. */\nconst BONE_FRACTION_OF_FFM = 0.0497;\n\nconst round1 = (n: number) => Math.round(n * 10) / 10;\nconst round2 = (n: number) => Math.round(n * 100) / 100;\n\nexport function computeBodyComposition(input: BodyCompositionInput): BodyComposition {\n const { weightKg, bodyFatPct, heightCm, age } = input;\n const male = input.sex === 'male';\n const heightM = heightCm / 100;\n\n const bmi = heightM > 0 ? weightKg / (heightM * heightM) : 0;\n const fat = Math.max(0, Math.min(75, bodyFatPct)) / 100;\n const fatMassKg = weightKg * fat;\n const leanMassKg = weightKg - fatMassKg;\n\n const boneMassKg = leanMassKg * BONE_FRACTION_OF_FFM;\n const muscleMassKg = leanMassKg - boneMassKg;\n const bodyWaterKg = leanMassKg * WATER_FRACTION_OF_FFM;\n const proteinKg = Math.max(0, leanMassKg - bodyWaterKg - boneMassKg);\n\n // Skeletal muscle: Janssen (2000) when impedance is known, else a fraction of muscle.\n let skeletalMuscleMassKg: number;\n if (input.impedanceOhm && input.impedanceOhm > 0) {\n const sexTerm = male ? 3.825 : 0;\n skeletalMuscleMassKg =\n (0.401 * (heightCm * heightCm)) / input.impedanceOhm + sexTerm - 0.071 * age + 5.102;\n skeletalMuscleMassKg = Math.max(0, Math.min(muscleMassKg, skeletalMuscleMassKg));\n } else {\n skeletalMuscleMassKg = muscleMassKg * (male ? 0.68 : 0.62);\n }\n\n // Katch-McArdle: basal metabolic rate from lean mass.\n const bmr = Math.round(370 + 21.6 * leanMassKg);\n\n // Metabolic age: how old the person's BMR looks against the BMR a lean,\n // average person of their height would have at each age. Clamped to 18-80.\n const metabolicAge = estimateMetabolicAge(bmr, heightCm, male, age);\n\n // Visceral fat rating: rises with body-fat mass and age; a standard-style\n // index (not a clinical measure), clamped to the usual 1-59 range.\n const visceralFat = Math.max(\n 1,\n Math.min(59, Math.round((fatMassKg * (male ? 1.0 : 0.85)) / 2.2 + age / 12 - 3)),\n );\n // Subcutaneous fat is the body fat that is not visceral.\n const subcutaneousFatPct = Math.max(0, bodyFatPct - visceralFat * 0.33);\n\n const pct = (kg: number) => (weightKg > 0 ? (kg / weightKg) * 100 : 0);\n return {\n bmi: round1(bmi),\n fatMassKg: round2(fatMassKg),\n leanMassKg: round2(leanMassKg),\n muscleMassKg: round2(muscleMassKg),\n musclePct: round1(pct(muscleMassKg)),\n skeletalMuscleMassKg: round2(skeletalMuscleMassKg),\n skeletalMusclePct: round1(pct(skeletalMuscleMassKg)),\n boneMassKg: round2(boneMassKg),\n bonePct: round1(pct(boneMassKg)),\n bodyWaterKg: round2(bodyWaterKg),\n bodyWaterPct: round1(pct(bodyWaterKg)),\n proteinKg: round2(proteinKg),\n proteinPct: round1(pct(proteinKg)),\n bmr,\n metabolicAge,\n visceralFat,\n subcutaneousFatPct: round1(subcutaneousFatPct),\n };\n}\n\n/** The composition as labelled rows for a details view, in the person's units. */\nexport function compositionRows(\n c: BodyComposition,\n units: 'metric' | 'imperial' = 'metric',\n): Array<{ label: string; value: string }> {\n const kg = (v: number) =>\n units === 'imperial' ? `${Math.round((v / 0.45359237) * 10) / 10} lb` : `${v} kg`;\n const pct = (v: number) => `${v}%`;\n return [\n { label: 'BMI', value: String(c.bmi) },\n { label: 'Fat mass', value: kg(c.fatMassKg) },\n { label: 'Fat-free mass', value: kg(c.leanMassKg) },\n { label: 'Muscle mass', value: kg(c.muscleMassKg) },\n { label: 'Muscle', value: pct(c.musclePct) },\n { label: 'Skeletal muscle', value: kg(c.skeletalMuscleMassKg) },\n { label: 'Bone mass', value: kg(c.boneMassKg) },\n { label: 'Body water', value: pct(c.bodyWaterPct) },\n { label: 'Protein', value: pct(c.proteinPct) },\n { label: 'BMR', value: `${c.bmr} kcal` },\n { label: 'Metabolic age', value: `${c.metabolicAge} yrs` },\n { label: 'Visceral fat', value: String(c.visceralFat) },\n { label: 'Subcutaneous fat', value: pct(c.subcutaneousFatPct) },\n ];\n}\n\n/** Compare the person's BMR to the typical BMR by age for their height and sex. */\nfunction estimateMetabolicAge(bmr: number, heightCm: number, male: boolean, age: number): number {\n // Typical fat-free mass by age (slow decline past 25), then its Katch-McArdle BMR.\n const ffmAt = (a: number) => {\n const base = male ? 0.407 * heightCm - 15 : 0.357 * heightCm - 13;\n const decline = a > 25 ? (a - 25) * 0.1 : 0;\n return Math.max(20, base - decline);\n };\n const bmrAt = (a: number) => 370 + 21.6 * ffmAt(a);\n let best = age;\n let bestDiff = Infinity;\n for (let a = 18; a <= 80; a++) {\n const diff = Math.abs(bmrAt(a) - bmr);\n if (diff < bestDiff) {\n bestDiff = diff;\n best = a;\n }\n }\n return best;\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"readings.js","sources":["../../../src/features/devices/readings.ts"],"sourcesContent":["/**\n * What a paired Bluetooth device measured, and how it reaches the Fitness\n * backend.\n *\n * The backend keeps ONE day per source and replaces it whole on every upload,\n * so a reading is never sent alone: the app keeps every reading it took (the\n * device store), and each upload rebuilds the full `device` day for the dates\n * that changed. A blood-pressure reading in the evening never wipes the\n * morning's weigh-in.\n *\n * Reading ids are stable (device + what + when): a monitor that sends its\n * whole memory on every connection, or the same reading arriving twice, is\n * stored once.\n */\n\nimport { sanitizeDay, hasData } from '../health/buildDays';\nimport type { TimedValue } from '../health/model';\nimport type { HealthDay, HealthReading, HealthWorkout, MealRelation } from '../health/types';\nimport type { ZoneClock } from '../health/time';\nimport { zoneMinutes } from '../health/zones';\n\ninterface ReadingBase {\n id: string;\n /** Epoch ms of the measurement. */\n at: number;\n deviceId: string;\n deviceName: string;\n}\n\nexport interface BodyReading extends ReadingBase {\n kind: 'body';\n weightKg?: number;\n bodyFatPct?: number;\n leanMassKg?: number;\n bmi?: number;\n /**\n * Whole-body impedance in ohms, when the scale sends it. A scale that only\n * reports weight and impedance (RENPHO's common protocol) leaves body fat\n * to Yantra's own estimate; one that computes body fat itself (R-A017) also\n * fills bodyFatPct and bmi.\n */\n impedanceOhm?: number;\n}\n\nexport interface BloodPressureReading extends ReadingBase {\n kind: 'blood-pressure';\n systolic: number;\n diastolic: number;\n pulse?: number;\n /** What the monitor flagged (moved, loose cuff, irregular pulse), in words. */\n problems?: string[];\n}\n\nexport interface TemperatureReading extends ReadingBase {\n kind: 'temperature';\n celsius: number;\n}\n\nexport interface OxygenReading extends ReadingBase {\n kind: 'spo2';\n spo2: number;\n pulse?: number;\n}\n\nexport interface GlucoseReading extends ReadingBase {\n kind: 'glucose';\n mgdl: number;\n meal?: MealRelation;\n}\n\n/** A heart-rate strap worn for a session: the samples, summed up when it ended. */\nexport interface HeartRateSession extends ReadingBase {\n kind: 'heart-rate';\n /** `at` is the start. */\n end: number;\n /** run | walk | cycle | strength | hiit | other, as the person picked it. */\n workoutType: string;\n avgHr: number;\n maxHr: number;\n /** At most one sample every few seconds (see thinSamples); emptied once saved, see compactSession. */\n samples: TimedValue[];\n /** Minutes per heart-rate zone, kept when the samples are let go. */\n zoneMinutes?: number[];\n}\n\n/**\n * A finished exercise a device recorded itself: a jump-rope session or a\n * treadmill walk/run. Becomes one HealthWorkout in the day (readings with no\n * heart-rate samples, unlike HeartRateSession).\n */\nexport interface WorkoutReading extends ReadingBase {\n kind: 'workout';\n /** `at` is the start. */\n end: number;\n /** jump-rope | run | walk | ... lowercased. */\n workoutType: string;\n durationMin: number;\n calories?: number;\n distanceMeters?: number;\n /** Jump rope only: the number of skips. */\n jumps?: number;\n avgHr?: number;\n maxHr?: number;\n}\n\n/** A tape-measure girth reading of one body part. Only the waist has a home in the day. */\nexport interface BodyMeasurementReading extends ReadingBase {\n kind: 'body-measurement';\n /** waist | chest | hip | left_arm | ... as the tape reported it. */\n bodyPart: string;\n cm: number;\n}\n\nexport type DeviceReading =\n | BodyReading\n | BloodPressureReading\n | TemperatureReading\n | OxygenReading\n | GlucoseReading\n | HeartRateSession\n | WorkoutReading\n | BodyMeasurementReading;\n\nconst round1 = (n: number) => Math.round(n * 10) / 10;\n\n/** A stable id: the same measurement from the same device always gets the same one. */\nexport function readingId(deviceId: string, kind: DeviceReading['kind'], at: number, extra?: string | number): string {\n return [deviceId, kind, Math.round(at / 1000), extra].filter((p) => p !== undefined && p !== '').join(':');\n}\n\n/** Keep one heart-rate sample per `everyMs`: enough for zones, few enough to store and save. */\nexport function thinSamples(samples: readonly TimedValue[], everyMs = 5_000): TimedValue[] {\n const out: TimedValue[] = [];\n let last = -Infinity;\n for (const s of [...samples].sort((a, b) => a.t - b.t)) {\n if (s.t - last >= everyMs) {\n out.push(s);\n last = s.t;\n }\n }\n return out;\n}\n\nconst latestOf = <T extends DeviceReading>(list: readonly T[], has: (r: T) => boolean): T | undefined =>\n list.filter(has).reduce<T | undefined>((a, b) => (!a || b.at >= a.at ? b : a), undefined);\n\nexport interface DeviceDaysOptions {\n clock: ZoneClock;\n syncedAt: string;\n /** 208 - 0.7 x age, for heart-rate zones; undefined when the birth date is unknown. */\n maxHr?: number;\n /** Only these dates (the ones a new reading touched); every date when omitted. */\n dates?: ReadonlySet<string>;\n}\n\n/** Every reading -> one `device` HealthDay per local date, cleaned exactly as the backend cleans. */\nexport function deviceHealthDays(\n readings: readonly DeviceReading[],\n opts: DeviceDaysOptions,\n): { days: HealthDay[]; dropped: string[] } {\n const byDate = new Map<string, DeviceReading[]>();\n for (const r of readings) {\n const date = opts.clock.dateOf(r.at);\n if (opts.dates && !opts.dates.has(date)) continue;\n byDate.set(date, [...(byDate.get(date) ?? []), r]);\n }\n const dropped: string[] = [];\n const days: HealthDay[] = [];\n for (const [date, list] of [...byDate.entries()].sort(([a], [b]) => a.localeCompare(b))) {\n const day: HealthDay = { date, source: 'device' };\n const body = list.filter((r): r is BodyReading => r.kind === 'body');\n const weight = latestOf(body, (r) => r.weightKg !== undefined);\n if (weight) day.weightKg = weight.weightKg;\n const fat = latestOf(body, (r) => r.bodyFatPct !== undefined);\n if (fat) day.bodyFatPct = fat.bodyFatPct;\n const lean = latestOf(body, (r) => r.leanMassKg !== undefined);\n if (lean) day.leanMassKg = lean.leanMassKg;\n const bmi = latestOf(body, (r) => r.bmi !== undefined);\n if (bmi) day.bmi = bmi.bmi;\n const temp = latestOf(\n list.filter((r): r is TemperatureReading => r.kind === 'temperature'),\n () => true,\n );\n if (temp) day.bodyTempC = temp.celsius;\n const spo2 = latestOf(\n list.filter((r): r is OxygenReading => r.kind === 'spo2'),\n () => true,\n );\n if (spo2) day.spo2 = spo2.spo2;\n const waist = latestOf(\n list.filter((r): r is BodyMeasurementReading => r.kind === 'body-measurement' && r.bodyPart === 'waist'),\n () => true,\n );\n if (waist) day.waistCm = waist.cm;\n\n const readingsOut: HealthReading[] = [];\n for (const r of list) {\n if (r.kind === 'blood-pressure') {\n readingsOut.push({\n id: r.id,\n at: new Date(r.at).toISOString(),\n kind: 'blood-pressure',\n systolic: r.systolic,\n diastolic: r.diastolic,\n ...(r.pulse !== undefined ? { pulse: r.pulse } : {}),\n device: r.deviceName,\n });\n } else if (r.kind === 'glucose') {\n readingsOut.push({\n id: r.id,\n at: new Date(r.at).toISOString(),\n kind: 'glucose',\n glucoseMgDl: r.mgdl,\n ...(r.meal ? { meal: r.meal } : {}),\n device: r.deviceName,\n });\n }\n }\n if (readingsOut.length) day.readings = readingsOut.sort((a, b) => a.at.localeCompare(b.at));\n\n const workouts: HealthWorkout[] = list\n .filter((r): r is HeartRateSession => r.kind === 'heart-rate')\n .sort((a, b) => a.at - b.at)\n .map((s) => {\n const w: HealthWorkout = {\n id: s.id,\n start: new Date(s.at).toISOString(),\n end: new Date(s.end).toISOString(),\n type: s.workoutType,\n durationMin: round1((s.end - s.at) / 60_000),\n avgHr: s.avgHr,\n maxHr: s.maxHr,\n };\n if (opts.maxHr && s.samples.length) {\n w.zoneMinutes = zoneMinutes(s.samples, { start: s.at, end: s.end }, opts.maxHr);\n } else if (s.zoneMinutes) w.zoneMinutes = s.zoneMinutes;\n return w;\n });\n // Device-recorded workouts (jump rope, treadmill): same HealthWorkout shape, no HR samples.\n for (const s of list.filter((r): r is WorkoutReading => r.kind === 'workout').sort((a, b) => a.at - b.at)) {\n const w: HealthWorkout = {\n id: s.id,\n start: new Date(s.at).toISOString(),\n end: new Date(s.end).toISOString(),\n type: s.workoutType,\n durationMin: round1(s.durationMin),\n ...(s.calories !== undefined ? { calories: s.calories } : {}),\n ...(s.distanceMeters !== undefined ? { distanceMeters: s.distanceMeters } : {}),\n ...(s.avgHr !== undefined ? { avgHr: s.avgHr } : {}),\n ...(s.maxHr !== undefined ? { maxHr: s.maxHr } : {}),\n };\n workouts.push(w);\n }\n if (workouts.length) day.workouts = workouts.sort((a, b) => a.start.localeCompare(b.start));\n\n const clean = sanitizeDay(day, dropped);\n if (hasData(clean)) days.push({ ...clean, syncedAt: opts.syncedAt });\n }\n return { days, dropped };\n}\n\n/** One line for a reading, as the person reads it (\"82.4 kg, body fat 23.1%\"). */\nexport function describeReading(r: DeviceReading, units: 'metric' | 'imperial' = 'metric'): string {\n const kg = (v: number) => (units === 'imperial' ? `${round1(v / 0.45359237)} lb` : `${round1(v)} kg`);\n switch (r.kind) {\n case 'body': {\n const parts: string[] = [];\n if (r.weightKg !== undefined) parts.push(kg(r.weightKg));\n if (r.bodyFatPct !== undefined) parts.push(`body fat ${round1(r.bodyFatPct)}%`);\n if (r.bmi !== undefined) parts.push(`BMI ${round1(r.bmi)}`);\n return parts.join(', ') || 'A measurement with no weight';\n }\n case 'blood-pressure':\n return `${Math.round(r.systolic)}/${Math.round(r.diastolic)} mmHg${r.pulse ? `, pulse ${Math.round(r.pulse)}` : ''}`;\n case 'temperature':\n return units === 'imperial' ? `${round1((r.celsius * 9) / 5 + 32)} °F` : `${round1(r.celsius)} °C`;\n case 'spo2':\n return `Blood oxygen ${Math.round(r.spo2)}%${r.pulse ? `, pulse ${Math.round(r.pulse)}` : ''}`;\n case 'glucose':\n return `${Math.round(r.mgdl)} mg/dL${r.meal ? `, ${r.meal.replace('-', ' ')}` : ''}`;\n case 'heart-rate': {\n const minutes = Math.round((r.end - r.at) / 60_000);\n return `${minutes} min, average ${Math.round(r.avgHr)} bpm, max ${Math.round(r.maxHr)}`;\n }\n case 'workout': {\n const parts: string[] = [`${Math.round(r.durationMin)} min`];\n if (r.jumps !== undefined) parts.unshift(`${r.jumps} jumps`);\n if (r.distanceMeters !== undefined) parts.push(`${round1(r.distanceMeters / 1000)} km`);\n if (r.calories !== undefined) parts.push(`${Math.round(r.calories)} kcal`);\n return parts.join(', ');\n }\n case 'body-measurement': {\n const part = r.bodyPart.replace(/_/g, ' ');\n return units === 'imperial' ? `${part} ${round1(r.cm / 2.54)} in` : `${part} ${round1(r.cm)} cm`;\n }\n default:\n return '';\n }\n}\n\n/**\n * A session's samples are only needed until they are uploaded and saved to\n * the health store; after that the zones are kept and the samples let go, so\n * the phone's store stays small.\n */\nexport function compactSession(s: HeartRateSession, maxHr: number | undefined): HeartRateSession {\n if (!s.samples.length) return s;\n const zones = maxHr ? zoneMinutes(s.samples, { start: s.at, end: s.end }, maxHr) : s.zoneMinutes;\n return { ...s, samples: [], ...(zones ? { zoneMinutes: zones } : {}) };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"readings.js","sources":["../../../src/features/devices/readings.ts"],"sourcesContent":["/**\n * What a paired Bluetooth device measured, and how it reaches the Fitness\n * backend.\n *\n * The backend keeps ONE day per source and replaces it whole on every upload,\n * so a reading is never sent alone: the app keeps every reading it took (the\n * device store), and each upload rebuilds the full `device` day for the dates\n * that changed. A blood-pressure reading in the evening never wipes the\n * morning's weigh-in.\n *\n * Reading ids are stable (device + what + when): a monitor that sends its\n * whole memory on every connection, or the same reading arriving twice, is\n * stored once.\n */\n\nimport type { BodyComposition } from './bodyComposition';\nimport { sanitizeDay, hasData } from '../health/buildDays';\nimport type { TimedValue } from '../health/model';\nimport type { HealthDay, HealthReading, HealthWorkout, MealRelation } from '../health/types';\nimport type { ZoneClock } from '../health/time';\nimport { zoneMinutes } from '../health/zones';\n\ninterface ReadingBase {\n id: string;\n /** Epoch ms of the measurement. */\n at: number;\n deviceId: string;\n deviceName: string;\n}\n\nexport interface BodyReading extends ReadingBase {\n kind: 'body';\n weightKg?: number;\n bodyFatPct?: number;\n leanMassKg?: number;\n bmi?: number;\n /**\n * Whole-body impedance in ohms, when the scale sends it. A scale that only\n * reports weight and impedance (RENPHO's common protocol) leaves body fat\n * to Yantra's own estimate; one that computes body fat itself (R-A017) also\n * fills bodyFatPct and bmi.\n */\n impedanceOhm?: number;\n /**\n * The full body composition (muscle, bone, water, BMR, metabolic age ...),\n * computed from weight + body fat + the person's height/age/sex when all are\n * known (bodyComposition.ts). Shown on the reading; the backend day keeps\n * the fields it supports.\n */\n composition?: BodyComposition;\n}\n\nexport interface BloodPressureReading extends ReadingBase {\n kind: 'blood-pressure';\n systolic: number;\n diastolic: number;\n pulse?: number;\n /** What the monitor flagged (moved, loose cuff, irregular pulse), in words. */\n problems?: string[];\n}\n\nexport interface TemperatureReading extends ReadingBase {\n kind: 'temperature';\n celsius: number;\n}\n\nexport interface OxygenReading extends ReadingBase {\n kind: 'spo2';\n spo2: number;\n pulse?: number;\n}\n\nexport interface GlucoseReading extends ReadingBase {\n kind: 'glucose';\n mgdl: number;\n meal?: MealRelation;\n}\n\n/** A heart-rate strap worn for a session: the samples, summed up when it ended. */\nexport interface HeartRateSession extends ReadingBase {\n kind: 'heart-rate';\n /** `at` is the start. */\n end: number;\n /** run | walk | cycle | strength | hiit | other, as the person picked it. */\n workoutType: string;\n avgHr: number;\n maxHr: number;\n /** At most one sample every few seconds (see thinSamples); emptied once saved, see compactSession. */\n samples: TimedValue[];\n /** Minutes per heart-rate zone, kept when the samples are let go. */\n zoneMinutes?: number[];\n}\n\n/**\n * A finished exercise a device recorded itself: a jump-rope session or a\n * treadmill walk/run. Becomes one HealthWorkout in the day (readings with no\n * heart-rate samples, unlike HeartRateSession).\n */\nexport interface WorkoutReading extends ReadingBase {\n kind: 'workout';\n /** `at` is the start. */\n end: number;\n /** jump-rope | run | walk | ... lowercased. */\n workoutType: string;\n durationMin: number;\n calories?: number;\n distanceMeters?: number;\n /** Jump rope only: the number of skips. */\n jumps?: number;\n avgHr?: number;\n maxHr?: number;\n}\n\n/** A tape-measure girth reading of one body part. Only the waist has a home in the day. */\nexport interface BodyMeasurementReading extends ReadingBase {\n kind: 'body-measurement';\n /** waist | chest | hip | left_arm | ... as the tape reported it. */\n bodyPart: string;\n cm: number;\n}\n\nexport type DeviceReading =\n | BodyReading\n | BloodPressureReading\n | TemperatureReading\n | OxygenReading\n | GlucoseReading\n | HeartRateSession\n | WorkoutReading\n | BodyMeasurementReading;\n\nconst round1 = (n: number) => Math.round(n * 10) / 10;\n\n/** A stable id: the same measurement from the same device always gets the same one. */\nexport function readingId(deviceId: string, kind: DeviceReading['kind'], at: number, extra?: string | number): string {\n return [deviceId, kind, Math.round(at / 1000), extra].filter((p) => p !== undefined && p !== '').join(':');\n}\n\n/** Keep one heart-rate sample per `everyMs`: enough for zones, few enough to store and save. */\nexport function thinSamples(samples: readonly TimedValue[], everyMs = 5_000): TimedValue[] {\n const out: TimedValue[] = [];\n let last = -Infinity;\n for (const s of [...samples].sort((a, b) => a.t - b.t)) {\n if (s.t - last >= everyMs) {\n out.push(s);\n last = s.t;\n }\n }\n return out;\n}\n\nconst latestOf = <T extends DeviceReading>(list: readonly T[], has: (r: T) => boolean): T | undefined =>\n list.filter(has).reduce<T | undefined>((a, b) => (!a || b.at >= a.at ? b : a), undefined);\n\nexport interface DeviceDaysOptions {\n clock: ZoneClock;\n syncedAt: string;\n /** 208 - 0.7 x age, for heart-rate zones; undefined when the birth date is unknown. */\n maxHr?: number;\n /** Only these dates (the ones a new reading touched); every date when omitted. */\n dates?: ReadonlySet<string>;\n}\n\n/** Every reading -> one `device` HealthDay per local date, cleaned exactly as the backend cleans. */\nexport function deviceHealthDays(\n readings: readonly DeviceReading[],\n opts: DeviceDaysOptions,\n): { days: HealthDay[]; dropped: string[] } {\n const byDate = new Map<string, DeviceReading[]>();\n for (const r of readings) {\n const date = opts.clock.dateOf(r.at);\n if (opts.dates && !opts.dates.has(date)) continue;\n byDate.set(date, [...(byDate.get(date) ?? []), r]);\n }\n const dropped: string[] = [];\n const days: HealthDay[] = [];\n for (const [date, list] of [...byDate.entries()].sort(([a], [b]) => a.localeCompare(b))) {\n const day: HealthDay = { date, source: 'device' };\n const body = list.filter((r): r is BodyReading => r.kind === 'body');\n const weight = latestOf(body, (r) => r.weightKg !== undefined);\n if (weight) day.weightKg = weight.weightKg;\n const fat = latestOf(body, (r) => r.bodyFatPct !== undefined);\n if (fat) day.bodyFatPct = fat.bodyFatPct;\n const lean = latestOf(body, (r) => r.leanMassKg !== undefined);\n if (lean) day.leanMassKg = lean.leanMassKg;\n const bmi = latestOf(body, (r) => r.bmi !== undefined);\n if (bmi) day.bmi = bmi.bmi;\n const temp = latestOf(\n list.filter((r): r is TemperatureReading => r.kind === 'temperature'),\n () => true,\n );\n if (temp) day.bodyTempC = temp.celsius;\n const spo2 = latestOf(\n list.filter((r): r is OxygenReading => r.kind === 'spo2'),\n () => true,\n );\n if (spo2) day.spo2 = spo2.spo2;\n const waist = latestOf(\n list.filter((r): r is BodyMeasurementReading => r.kind === 'body-measurement' && r.bodyPart === 'waist'),\n () => true,\n );\n if (waist) day.waistCm = waist.cm;\n\n const readingsOut: HealthReading[] = [];\n for (const r of list) {\n if (r.kind === 'blood-pressure') {\n readingsOut.push({\n id: r.id,\n at: new Date(r.at).toISOString(),\n kind: 'blood-pressure',\n systolic: r.systolic,\n diastolic: r.diastolic,\n ...(r.pulse !== undefined ? { pulse: r.pulse } : {}),\n device: r.deviceName,\n });\n } else if (r.kind === 'glucose') {\n readingsOut.push({\n id: r.id,\n at: new Date(r.at).toISOString(),\n kind: 'glucose',\n glucoseMgDl: r.mgdl,\n ...(r.meal ? { meal: r.meal } : {}),\n device: r.deviceName,\n });\n }\n }\n if (readingsOut.length) day.readings = readingsOut.sort((a, b) => a.at.localeCompare(b.at));\n\n const workouts: HealthWorkout[] = list\n .filter((r): r is HeartRateSession => r.kind === 'heart-rate')\n .sort((a, b) => a.at - b.at)\n .map((s) => {\n const w: HealthWorkout = {\n id: s.id,\n start: new Date(s.at).toISOString(),\n end: new Date(s.end).toISOString(),\n type: s.workoutType,\n durationMin: round1((s.end - s.at) / 60_000),\n avgHr: s.avgHr,\n maxHr: s.maxHr,\n };\n if (opts.maxHr && s.samples.length) {\n w.zoneMinutes = zoneMinutes(s.samples, { start: s.at, end: s.end }, opts.maxHr);\n } else if (s.zoneMinutes) w.zoneMinutes = s.zoneMinutes;\n return w;\n });\n // Device-recorded workouts (jump rope, treadmill): same HealthWorkout shape, no HR samples.\n for (const s of list.filter((r): r is WorkoutReading => r.kind === 'workout').sort((a, b) => a.at - b.at)) {\n const w: HealthWorkout = {\n id: s.id,\n start: new Date(s.at).toISOString(),\n end: new Date(s.end).toISOString(),\n type: s.workoutType,\n durationMin: round1(s.durationMin),\n ...(s.calories !== undefined ? { calories: s.calories } : {}),\n ...(s.distanceMeters !== undefined ? { distanceMeters: s.distanceMeters } : {}),\n ...(s.avgHr !== undefined ? { avgHr: s.avgHr } : {}),\n ...(s.maxHr !== undefined ? { maxHr: s.maxHr } : {}),\n };\n workouts.push(w);\n }\n if (workouts.length) day.workouts = workouts.sort((a, b) => a.start.localeCompare(b.start));\n\n const clean = sanitizeDay(day, dropped);\n if (hasData(clean)) days.push({ ...clean, syncedAt: opts.syncedAt });\n }\n return { days, dropped };\n}\n\n/** One line for a reading, as the person reads it (\"82.4 kg, body fat 23.1%\"). */\nexport function describeReading(r: DeviceReading, units: 'metric' | 'imperial' = 'metric'): string {\n const kg = (v: number) => (units === 'imperial' ? `${round1(v / 0.45359237)} lb` : `${round1(v)} kg`);\n switch (r.kind) {\n case 'body': {\n const parts: string[] = [];\n if (r.weightKg !== undefined) parts.push(kg(r.weightKg));\n if (r.bodyFatPct !== undefined) parts.push(`body fat ${round1(r.bodyFatPct)}%`);\n if (r.bmi !== undefined) parts.push(`BMI ${round1(r.bmi)}`);\n return parts.join(', ') || 'A measurement with no weight';\n }\n case 'blood-pressure':\n return `${Math.round(r.systolic)}/${Math.round(r.diastolic)} mmHg${r.pulse ? `, pulse ${Math.round(r.pulse)}` : ''}`;\n case 'temperature':\n return units === 'imperial' ? `${round1((r.celsius * 9) / 5 + 32)} °F` : `${round1(r.celsius)} °C`;\n case 'spo2':\n return `Blood oxygen ${Math.round(r.spo2)}%${r.pulse ? `, pulse ${Math.round(r.pulse)}` : ''}`;\n case 'glucose':\n return `${Math.round(r.mgdl)} mg/dL${r.meal ? `, ${r.meal.replace('-', ' ')}` : ''}`;\n case 'heart-rate': {\n const minutes = Math.round((r.end - r.at) / 60_000);\n return `${minutes} min, average ${Math.round(r.avgHr)} bpm, max ${Math.round(r.maxHr)}`;\n }\n case 'workout': {\n const parts: string[] = [`${Math.round(r.durationMin)} min`];\n if (r.jumps !== undefined) parts.unshift(`${r.jumps} jumps`);\n if (r.distanceMeters !== undefined) parts.push(`${round1(r.distanceMeters / 1000)} km`);\n if (r.calories !== undefined) parts.push(`${Math.round(r.calories)} kcal`);\n return parts.join(', ');\n }\n case 'body-measurement': {\n const part = r.bodyPart.replace(/_/g, ' ');\n return units === 'imperial' ? `${part} ${round1(r.cm / 2.54)} in` : `${part} ${round1(r.cm)} cm`;\n }\n default:\n return '';\n }\n}\n\n/**\n * A session's samples are only needed until they are uploaded and saved to\n * the health store; after that the zones are kept and the samples let go, so\n * the phone's store stays small.\n */\nexport function compactSession(s: HeartRateSession, maxHr: number | undefined): HeartRateSession {\n if (!s.samples.length) return s;\n const zones = maxHr ? zoneMinutes(s.samples, { start: s.at, end: s.end }, maxHr) : s.zoneMinutes;\n return { ...s, samples: [], ...(zones ? { zoneMinutes: zones } : {}) };\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {deviceKind}from'./catalog.js';import {describeBleError}from'./link.js';import {thinSamples,readingId}from'./readings.js';import'./brands/frames.js';import'./brands/uuids.js';import'./gatt/uuids.js';import {detectBrand}from'./brands/detect.js';import {startDriver}from'./drivers.js';var __defProp = Object.defineProperty;
1
+ import {deviceKind}from'./catalog.js';import {describeBleError}from'./link.js';import {thinSamples,readingId}from'./readings.js';import'./brands/frames.js';import'./brands/uuids.js';import'./gatt/uuids.js';import {detectBrand}from'./brands/detect.js';import {startDriver}from'./drivers.js';import {computeBodyComposition}from'./bodyComposition.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -24,6 +24,26 @@ function ageFrom(birthDate, now) {
24
24
  const t = Date.parse(`${birthDate}T00:00:00Z`);
25
25
  return Number.isFinite(t) ? Math.floor((now - t) / (365.25 * 864e5)) : void 0;
26
26
  }
27
+ function enrichWithComposition(reading, facts) {
28
+ var _a, _b, _c;
29
+ if (reading.kind !== "body" || reading.weightKg === void 0 || reading.bodyFatPct === void 0) {
30
+ return reading;
31
+ }
32
+ if (!facts.heightCm || facts.age === void 0) return reading;
33
+ const composition = computeBodyComposition({
34
+ weightKg: reading.weightKg,
35
+ bodyFatPct: reading.bodyFatPct,
36
+ heightCm: facts.heightCm,
37
+ age: facts.age,
38
+ sex: (_a = facts.sex) != null ? _a : "unspecified",
39
+ impedanceOhm: reading.impedanceOhm
40
+ });
41
+ return __spreadProps(__spreadValues({}, reading), {
42
+ bmi: (_b = reading.bmi) != null ? _b : composition.bmi,
43
+ leanMassKg: (_c = reading.leanMassKg) != null ? _c : composition.leanMassKg,
44
+ composition
45
+ });
46
+ }
27
47
  class DeviceSession {
28
48
  constructor(deps) {
29
49
  this.deps = deps;
@@ -187,7 +207,7 @@ class DeviceSession {
187
207
  } : void 0,
188
208
  scaleUser: paired == null ? void 0 : paired.scaleUser,
189
209
  saveScaleUser: (user) => store.saveScaleUser(link.id, user),
190
- onReading: (r) => void this.keep([r]),
210
+ onReading: (r) => void this.keep([enrichWithComposition(r, facts)]),
191
211
  onLive: (v) => this.onLive(v),
192
212
  onNotice: (m) => this.set({
193
213
  notices: [...this.snapshot.notices, m]
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sources":["../../../src/features/devices/session.ts"],"sourcesContent":["/**\n * One \"take a reading\" from start to end, for the screen: is Bluetooth on and\n * allowed, find the device (or the one already paired), connect, run its\n * driver, keep what it measures, and end cleanly when it goes to sleep (a\n * scale switches off seconds after a weighing; that is the normal end, not an\n * error).\n *\n * Heart-rate straps and continuous oximeters stream: the person starts and\n * stops a session (heart rate) or saves the value they see (oxygen).\n *\n * Plain class with injected transport and store, like the other stores: the\n * screen subscribes with useSyncExternalStore, tests drive it with fakes.\n */\nimport type { TimedValue } from '../health/model';\nimport { deviceKind, type DeviceKindId } from './catalog';\nimport { describeBleError, type BleTransport, type ConnectedLink, type FoundDevice, type RadioState } from './link';\nimport { detectBrand } from './brands';\nimport type { DeviceStore } from './deviceStore';\nimport { startDriver, type DriverHandle, type LiveValue, type PersonFacts } from './drivers';\nimport { readingId, thinSamples, type DeviceReading, type HeartRateSession } from './readings';\n\nexport type SessionState =\n | { step: 'starting' }\n | { step: 'unavailable'; reason: string }\n | { step: 'radio'; radio: Exclude<RadioState, 'ready'> }\n | { step: 'scanning'; found: FoundDevice[]; hint?: string }\n | { step: 'connecting'; device: FoundDevice }\n | { step: 'connected'; device: { id: string; name: string } }\n | { step: 'ended'; device: { id: string; name: string } }\n | { step: 'error'; message: string };\n\nexport interface SessionSnapshot {\n state: SessionState;\n kind: DeviceKindId;\n /** What this session measured, newest first. */\n readings: DeviceReading[];\n live?: LiveValue;\n recording?: { startedAt: number; workoutType: string; avgHr?: number; maxHr?: number };\n notices: string[];\n}\n\nexport interface SessionDeps {\n transport: BleTransport | null;\n store: Pick<DeviceStore, 'pair' | 'addReadings' | 'saveScaleUser' | 'person' | 'getSnapshot'>;\n kind: DeviceKindId;\n /** Reconnect to this paired device instead of offering a list. */\n deviceId?: string;\n now?: () => number;\n}\n\n/** Scanning this long without finding anything: tell the person how to wake it. */\nexport const SCAN_HINT_MS = 20_000;\n\nfunction ageFrom(birthDate: string | undefined, now: number): number | undefined {\n if (!birthDate) return undefined;\n const t = Date.parse(`${birthDate}T00:00:00Z`);\n return Number.isFinite(t) ? Math.floor((now - t) / (365.25 * 86_400_000)) : undefined;\n}\n\nexport class DeviceSession {\n private snapshot: SessionSnapshot;\n\n private listeners = new Set<() => void>();\n\n private stopScan: (() => void) | null = null;\n\n private link: ConnectedLink | null = null;\n\n private driver: DriverHandle | null = null;\n\n private hintTimer: ReturnType<typeof setTimeout> | null = null;\n\n private hr: { samples: TimedValue[]; sum: number; count: number; max: number } | null = null;\n\n private closed = false;\n\n constructor(private readonly deps: SessionDeps) {\n this.snapshot = { state: { step: 'starting' }, kind: deps.kind, readings: [], notices: [] };\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): SessionSnapshot => this.snapshot;\n\n private now(): number {\n return this.deps.now ? this.deps.now() : Date.now();\n }\n\n private set(patch: Partial<SessionSnapshot>) {\n if (this.closed) return;\n this.snapshot = { ...this.snapshot, ...patch };\n this.listeners.forEach((l) => l());\n }\n\n async start(): Promise<void> {\n const { transport } = this.deps;\n if (!transport) {\n this.set({\n state: { step: 'unavailable', reason: 'Bluetooth devices need the latest version of the Yantra app.' },\n });\n return;\n }\n if (!(await transport.requestPermissions())) {\n this.set({ state: { step: 'radio', radio: 'unauthorized' } });\n return;\n }\n const radio = await transport.radio();\n if (radio !== 'ready' && radio !== 'unknown') {\n this.set({ state: { step: 'radio', radio } });\n return;\n }\n this.scan();\n }\n\n /** Back to looking for the device (after the radio came on, or to measure again). */\n scan(): void {\n const { transport } = this.deps;\n if (!transport || this.closed) return;\n this.stopScan?.();\n this.set({ state: { step: 'scanning', found: [] } });\n this.hintTimer = setTimeout(() => {\n const s = this.snapshot.state;\n if (s.step === 'scanning' && !s.found.length) {\n this.set({ state: { ...s, hint: deviceKind(this.deps.kind).steps[0] } });\n }\n }, SCAN_HINT_MS);\n const kind = this.deps.kind;\n this.stopScan = transport.scan(\n {\n services: deviceKind(kind).services,\n // Brand devices do not advertise a standard service: recognise this kind of them.\n match: (adv) => {\n const brand = detectBrand(adv);\n return brand && brand.kind === kind ? brand : undefined;\n },\n },\n (found) => {\n const s = this.snapshot.state;\n if (s.step !== 'scanning') return;\n if (this.deps.deviceId && found.id === this.deps.deviceId) {\n void this.pick(found);\n return;\n }\n if (this.deps.deviceId) return;\n this.set({\n state: {\n ...s,\n hint: undefined,\n found: [...s.found, found].sort((a, b) => (b.rssi ?? -999) - (a.rssi ?? -999)),\n },\n });\n },\n (message) => this.set({ state: { step: 'error', message } }),\n );\n }\n\n async pick(found: FoundDevice): Promise<void> {\n const { transport, store } = this.deps;\n if (!transport) return;\n this.clearScan();\n this.set({ state: { step: 'connecting', device: found } });\n try {\n const link = await transport.connect(found.id, found.name, () => this.onDisconnect());\n this.link = link;\n const paired = store.getSnapshot().devices.find((d) => d.id === link.id);\n const person = await store.person();\n const facts: PersonFacts = {\n age: ageFrom(person?.birthDate, this.now()),\n sex: person?.sex,\n heightCm: person?.heightCm,\n birthDate: person?.birthDate,\n weightKg: paired?.lastWeightKg,\n };\n this.driver = await startDriver(this.deps.kind, link, {\n now: () => this.now(),\n person: facts,\n identity: found.protocol\n ? {\n protocol: found.protocol,\n mac: found.mac,\n deviceType: found.deviceType,\n model: found.model,\n kind: found.kind,\n }\n : undefined,\n scaleUser: paired?.scaleUser,\n saveScaleUser: (user) => store.saveScaleUser(link.id, user),\n onReading: (r) => void this.keep([r]),\n onLive: (v) => this.onLive(v),\n onNotice: (m) => this.set({ notices: [...this.snapshot.notices, m] }),\n });\n await store.pair({\n id: link.id,\n name: link.name,\n kind: this.deps.kind,\n ...(found.protocol ? { protocol: found.protocol } : {}),\n });\n this.set({ state: { step: 'connected', device: { id: link.id, name: link.name } } });\n } catch (err) {\n await this.link?.close();\n this.link = null;\n this.set({ state: { step: 'error', message: describeErrorOrOwn(err) } });\n }\n }\n\n private async keep(readings: DeviceReading[]): Promise<void> {\n const fresh = await this.deps.store.addReadings(readings);\n if (fresh.length) this.set({ readings: [...fresh.reverse(), ...this.snapshot.readings] });\n }\n\n private onLive(v: LiveValue) {\n this.set({ live: { ...this.snapshot.live, ...v } });\n if (this.hr && v.bpm) {\n const t = this.now();\n this.hr.samples.push({ t, value: v.bpm });\n this.hr.sum += v.bpm;\n this.hr.count += 1;\n this.hr.max = Math.max(this.hr.max, v.bpm);\n const rec = this.snapshot.recording;\n if (rec)\n this.set({ recording: { ...rec, avgHr: Math.round(this.hr.sum / this.hr.count), maxHr: this.hr.max } });\n }\n }\n\n /** Heart rate: start recording a session of the given kind (run, walk, cycle, strength ...). */\n startRecording(workoutType: string): void {\n this.hr = { samples: [], sum: 0, count: 0, max: 0 };\n this.set({ recording: { startedAt: this.now(), workoutType } });\n }\n\n /** Heart rate: end the session and keep it. Nothing is kept for a session with no heart rate. */\n async stopRecording(): Promise<HeartRateSession | null> {\n const rec = this.snapshot.recording;\n const hr = this.hr;\n this.hr = null;\n this.set({ recording: undefined });\n const device = this.link;\n if (!rec || !hr || !hr.count || !device) return null;\n const end = this.now();\n const session: HeartRateSession = {\n kind: 'heart-rate',\n id: readingId(device.id, 'heart-rate', rec.startedAt),\n at: rec.startedAt,\n end,\n deviceId: device.id,\n deviceName: device.name,\n workoutType: rec.workoutType,\n avgHr: Math.round(hr.sum / hr.count),\n maxHr: hr.max,\n samples: thinSamples(hr.samples),\n };\n await this.keep([session]);\n return session;\n }\n\n /** Continuous oximeter: keep the value on screen as a reading. */\n async saveLive(): Promise<void> {\n const live = this.snapshot.live;\n const device = this.link;\n if (!device || live?.spo2 === undefined) return;\n const at = this.now();\n await this.keep([\n {\n kind: 'spo2',\n id: readingId(device.id, 'spo2', at, live.spo2),\n at,\n deviceId: device.id,\n deviceName: device.name,\n spo2: live.spo2,\n ...(live.pulse !== undefined ? { pulse: live.pulse } : {}),\n },\n ]);\n }\n\n private onDisconnect() {\n this.driver?.stop();\n this.driver = null;\n const link = this.link;\n this.link = null;\n if (this.hr) void this.stopRecording();\n const s = this.snapshot.state;\n if (s.step === 'connected' && link) {\n // A scale or cuff switches off after measuring: the normal end.\n this.set({ state: { step: 'ended', device: { id: link.id, name: link.name } }, live: undefined });\n }\n }\n\n private clearScan() {\n this.stopScan?.();\n this.stopScan = null;\n if (this.hintTimer) clearTimeout(this.hintTimer);\n this.hintTimer = null;\n }\n\n /** Leave: finish what was being assembled, stop scanning, disconnect. */\n async close(): Promise<void> {\n if (this.hr) await this.stopRecording();\n this.clearScan();\n this.driver?.stop();\n this.driver = null;\n const link = this.link;\n this.link = null;\n this.closed = true;\n await link?.close();\n }\n}\n\nfunction describeErrorOrOwn(err: unknown): string {\n // The drivers' own messages are already in plain words (\"does not send weight the standard way\").\n if (err instanceof Error && /standard way|does not know how/.test(err.message)) return err.message;\n return describeBleError(err);\n}\n"],"names":["_a"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2EO,MAAM,YAAe,GAAA;AAC5B,SAAS,OAAA,CAAQ,WAA+B,GAAiC,EAAA;AAC/E,EAAI,IAAA,CAAC,WAAkB,OAAA,MAAA;AACvB,EAAA,MAAM,CAAI,GAAA,IAAA,CAAK,KAAM,CAAA,CAAA,EAAG,SAAS,CAAY,UAAA,CAAA,CAAA;AAC7C,EAAO,OAAA,MAAA,CAAO,QAAS,CAAA,CAAC,CAAI,GAAA,IAAA,CAAK,OAAO,GAAM,GAAA,CAAA,KAAM,MAAS,GAAA,KAAA,CAAW,CAAI,GAAA,MAAA;AAC9E;AACO,MAAM,aAAc,CAAA;AAAA,EAczB,YAA6B,IAAmB,EAAA;AAAnB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAb7B,IAAQ,aAAA,CAAA,IAAA,EAAA,UAAA,CAAA;AACR,IAAQ,aAAA,CAAA,IAAA,EAAA,WAAA,sBAAgB,GAAgB,EAAA,CAAA;AACxC,IAAA,aAAA,CAAA,IAAA,EAAQ,UAAgC,EAAA,IAAA,CAAA;AACxC,IAAA,aAAA,CAAA,IAAA,EAAQ,MAA6B,EAAA,IAAA,CAAA;AACrC,IAAA,aAAA,CAAA,IAAA,EAAQ,QAA8B,EAAA,IAAA,CAAA;AACtC,IAAA,aAAA,CAAA,IAAA,EAAQ,WAAkD,EAAA,IAAA,CAAA;AAC1D,IAAA,aAAA,CAAA,IAAA,EAAQ,IAKG,EAAA,IAAA,CAAA;AACX,IAAA,aAAA,CAAA,IAAA,EAAQ,QAAS,EAAA,KAAA,CAAA;AAWjB,IAAA,aAAA,CAAA,IAAA,EAAA,WAAA,EAAY,CAAC,QAAyB,KAAA;AACpC,MAAK,IAAA,CAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AAC3B,MAAA,OAAO,MAAM;AACX,QAAK,IAAA,CAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,OAChC;AAAA,KACF,CAAA;AACA,IAAA,aAAA,CAAA,IAAA,EAAA,aAAA,EAAc,MAAuB,IAAK,CAAA,QAAA,CAAA;AAfxC,IAAA,IAAA,CAAK,QAAW,GAAA;AAAA,MACd,KAAO,EAAA;AAAA,QACL,IAAM,EAAA;AAAA,OACR;AAAA,MACA,MAAM,IAAK,CAAA,IAAA;AAAA,MACX,UAAU,EAAC;AAAA,MACX,SAAS;AAAC,KACZ;AAAA;AACF,EAQQ,GAAc,GAAA;AACpB,IAAO,OAAA,IAAA,CAAK,KAAK,GAAM,GAAA,IAAA,CAAK,KAAK,GAAI,EAAA,GAAI,KAAK,GAAI,EAAA;AAAA;AACpD,EACQ,IAAI,KAAiC,EAAA;AAC3C,IAAA,IAAI,KAAK,MAAQ,EAAA;AACjB,IAAK,IAAA,CAAA,QAAA,GAAW,cACX,CAAA,cAAA,CAAA,EAAA,EAAA,IAAA,CAAK,QACL,CAAA,EAAA,KAAA,CAAA;AAEL,IAAA,IAAA,CAAK,SAAU,CAAA,OAAA,CAAQ,CAAK,CAAA,KAAA,CAAA,EAAG,CAAA;AAAA;AACjC,EACA,MAAM,KAAuB,GAAA;AAC3B,IAAM,MAAA;AAAA,MACJ;AAAA,QACE,IAAK,CAAA,IAAA;AACT,IAAA,IAAI,CAAC,SAAW,EAAA;AACd,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,IAAM,EAAA,aAAA;AAAA,UACN,MAAQ,EAAA;AAAA;AACV,OACD,CAAA;AACD,MAAA;AAAA;AAEF,IAAA,IAAI,CAAE,MAAM,SAAU,CAAA,kBAAA,EAAuB,EAAA;AAC3C,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,IAAM,EAAA,OAAA;AAAA,UACN,KAAO,EAAA;AAAA;AACT,OACD,CAAA;AACD,MAAA;AAAA;AAEF,IAAM,MAAA,KAAA,GAAQ,MAAM,SAAA,CAAU,KAAM,EAAA;AACpC,IAAI,IAAA,KAAA,KAAU,OAAW,IAAA,KAAA,KAAU,SAAW,EAAA;AAC5C,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,IAAM,EAAA,OAAA;AAAA,UACN;AAAA;AACF,OACD,CAAA;AACD,MAAA;AAAA;AAEF,IAAA,IAAA,CAAK,IAAK,EAAA;AAAA;AACZ;AAAA,EAGA,IAAa,GAAA;AA/Jf,IAAA,IAAA,EAAA;AAgKI,IAAM,MAAA;AAAA,MACJ;AAAA,QACE,IAAK,CAAA,IAAA;AACT,IAAI,IAAA,CAAC,SAAa,IAAA,IAAA,CAAK,MAAQ,EAAA;AAC/B,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,QAAL,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,IAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACP,KAAO,EAAA;AAAA,QACL,IAAM,EAAA,UAAA;AAAA,QACN,OAAO;AAAC;AACV,KACD,CAAA;AACD,IAAK,IAAA,CAAA,SAAA,GAAY,WAAW,MAAM;AAChC,MAAM,MAAA,CAAA,GAAI,KAAK,QAAS,CAAA,KAAA;AACxB,MAAA,IAAI,EAAE,IAAS,KAAA,UAAA,IAAc,CAAC,CAAA,CAAE,MAAM,MAAQ,EAAA;AAC5C,QAAA,IAAA,CAAK,GAAI,CAAA;AAAA,UACP,KAAA,EAAO,iCACF,CADE,CAAA,EAAA;AAAA,YAEL,MAAM,UAAW,CAAA,IAAA,CAAK,KAAK,IAAI,CAAA,CAAE,MAAM,CAAC;AAAA,WAC1C;AAAA,SACD,CAAA;AAAA;AACH,OACC,YAAY,CAAA;AACf,IAAM,MAAA,IAAA,GAAO,KAAK,IAAK,CAAA,IAAA;AACvB,IAAK,IAAA,CAAA,QAAA,GAAW,UAAU,IAAK,CAAA;AAAA,MAC7B,QAAA,EAAU,UAAW,CAAA,IAAI,CAAE,CAAA,QAAA;AAAA;AAAA,MAE3B,OAAO,CAAO,GAAA,KAAA;AACZ,QAAM,MAAA,KAAA,GAAQ,YAAY,GAAG,CAAA;AAC7B,QAAA,OAAO,KAAS,IAAA,KAAA,CAAM,IAAS,KAAA,IAAA,GAAO,KAAQ,GAAA,MAAA;AAAA;AAChD,OACC,CAAS,KAAA,KAAA;AACV,MAAM,MAAA,CAAA,GAAI,KAAK,QAAS,CAAA,KAAA;AACxB,MAAI,IAAA,CAAA,CAAE,SAAS,UAAY,EAAA;AAC3B,MAAA,IAAI,KAAK,IAAK,CAAA,QAAA,IAAY,MAAM,EAAO,KAAA,IAAA,CAAK,KAAK,QAAU,EAAA;AACzD,QAAK,KAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AACpB,QAAA;AAAA;AAEF,MAAI,IAAA,IAAA,CAAK,KAAK,QAAU,EAAA;AACxB,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAA,EAAO,iCACF,CADE,CAAA,EAAA;AAAA,UAEL,IAAM,EAAA,MAAA;AAAA,UACN,KAAA,EAAO,CAAC,GAAG,CAAE,CAAA,KAAA,EAAO,KAAK,CAAE,CAAA,IAAA,CAAK,CAAC,CAAA,EAAG,CAAG,KAAA;AA1MjD,YAAA,IAAAA,GAAA,EAAA,EAAA;AA0MqD,YAAAA,OAAAA,CAAAA,CAAAA,GAAAA,GAAA,EAAE,IAAF,KAAA,IAAA,GAAAA,MAAU,IAAS,KAAA,CAAA,EAAA,GAAA,CAAA,CAAE,SAAF,IAAU,GAAA,EAAA,GAAA,IAAA,CAAA;AAAA,WAAK;AAAA,SAC/E;AAAA,OACD,CAAA;AAAA,KACH,EAAG,CAAW,OAAA,KAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACrB,KAAO,EAAA;AAAA,QACL,IAAM,EAAA,OAAA;AAAA,QACN;AAAA;AACF,KACD,CAAC,CAAA;AAAA;AACJ,EACA,MAAM,KAAK,KAAmC,EAAA;AApNhD,IAAA,IAAA,EAAA;AAqNI,IAAM,MAAA;AAAA,MACJ,SAAA;AAAA,MACA;AAAA,QACE,IAAK,CAAA,IAAA;AACT,IAAA,IAAI,CAAC,SAAW,EAAA;AAChB,IAAA,IAAA,CAAK,SAAU,EAAA;AACf,IAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACP,KAAO,EAAA;AAAA,QACL,IAAM,EAAA,YAAA;AAAA,QACN,MAAQ,EAAA;AAAA;AACV,KACD,CAAA;AACD,IAAI,IAAA;AACF,MAAM,MAAA,IAAA,GAAO,MAAM,SAAA,CAAU,OAAQ,CAAA,KAAA,CAAM,EAAI,EAAA,KAAA,CAAM,IAAM,EAAA,MAAM,IAAK,CAAA,YAAA,EAAc,CAAA;AACpF,MAAA,IAAA,CAAK,IAAO,GAAA,IAAA;AACZ,MAAM,MAAA,MAAA,GAAS,KAAM,CAAA,WAAA,EAAc,CAAA,OAAA,CAAQ,KAAK,CAAK,CAAA,KAAA,CAAA,CAAE,EAAO,KAAA,IAAA,CAAK,EAAE,CAAA;AACrE,MAAM,MAAA,MAAA,GAAS,MAAM,KAAA,CAAM,MAAO,EAAA;AAClC,MAAA,MAAM,KAAqB,GAAA;AAAA,QACzB,KAAK,OAAQ,CAAA,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAQ,SAAW,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA,QAC1C,KAAK,MAAQ,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA,GAAA;AAAA,QACb,UAAU,MAAQ,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA,QAAA;AAAA,QAClB,WAAW,MAAQ,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA,SAAA;AAAA,QACnB,UAAU,MAAQ,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA;AAAA,OACpB;AACA,MAAA,IAAA,CAAK,SAAS,MAAM,WAAA,CAAY,IAAK,CAAA,IAAA,CAAK,MAAM,IAAM,EAAA;AAAA,QACpD,GAAA,EAAK,MAAM,IAAA,CAAK,GAAI,EAAA;AAAA,QACpB,MAAQ,EAAA,KAAA;AAAA,QACR,QAAA,EAAU,MAAM,QAAW,GAAA;AAAA,UACzB,UAAU,KAAM,CAAA,QAAA;AAAA,UAChB,KAAK,KAAM,CAAA,GAAA;AAAA,UACX,YAAY,KAAM,CAAA,UAAA;AAAA,UAClB,OAAO,KAAM,CAAA,KAAA;AAAA,UACb,MAAM,KAAM,CAAA;AAAA,SACV,GAAA,KAAA,CAAA;AAAA,QACJ,WAAW,MAAQ,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA,SAAA;AAAA,QACnB,eAAe,CAAQ,IAAA,KAAA,KAAA,CAAM,aAAc,CAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AAAA,QACxD,WAAW,CAAK,CAAA,KAAA,KAAK,KAAK,IAAK,CAAA,CAAC,CAAC,CAAC,CAAA;AAAA,QAClC,MAAQ,EAAA,CAAA,CAAA,KAAK,IAAK,CAAA,MAAA,CAAO,CAAC,CAAA;AAAA,QAC1B,QAAA,EAAU,CAAK,CAAA,KAAA,IAAA,CAAK,GAAI,CAAA;AAAA,UACtB,SAAS,CAAC,GAAG,IAAK,CAAA,QAAA,CAAS,SAAS,CAAC;AAAA,SACtC;AAAA,OACF,CAAA;AACD,MAAA,MAAM,MAAM,IAAK,CAAA,cAAA,CAAA;AAAA,QACf,IAAI,IAAK,CAAA,EAAA;AAAA,QACT,MAAM,IAAK,CAAA,IAAA;AAAA,QACX,IAAA,EAAM,KAAK,IAAK,CAAA;AAAA,OAAA,EACZ,MAAM,QAAW,GAAA;AAAA,QACnB,UAAU,KAAM,CAAA;AAAA,OAClB,GAAI,EACL,CAAA,CAAA;AACD,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,IAAM,EAAA,WAAA;AAAA,UACN,MAAQ,EAAA;AAAA,YACN,IAAI,IAAK,CAAA,EAAA;AAAA,YACT,MAAM,IAAK,CAAA;AAAA;AACb;AACF,OACD,CAAA;AAAA,aACM,GAAK,EAAA;AACZ,MAAM,OAAA,CAAA,EAAA,GAAA,IAAA,CAAK,SAAL,IAAW,GAAA,MAAA,GAAA,EAAA,CAAA,KAAA,EAAA,CAAA;AACjB,MAAA,IAAA,CAAK,IAAO,GAAA,IAAA;AACZ,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,IAAM,EAAA,OAAA;AAAA,UACN,OAAA,EAAS,mBAAmB,GAAG;AAAA;AACjC,OACD,CAAA;AAAA;AACH;AACF,EACA,MAAc,KAAK,QAA0C,EAAA;AAC3D,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,IAAK,CAAA,KAAA,CAAM,YAAY,QAAQ,CAAA;AACxD,IAAI,IAAA,KAAA,CAAM,MAAQ,EAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACzB,QAAA,EAAU,CAAC,GAAG,KAAA,CAAM,SAAW,EAAA,GAAG,IAAK,CAAA,QAAA,CAAS,QAAQ;AAAA,KACzD,CAAA;AAAA;AACH,EACQ,OAAO,CAAc,EAAA;AAC3B,IAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACP,IAAM,EAAA,cAAA,CAAA,cAAA,CAAA,EAAA,EACD,IAAK,CAAA,QAAA,CAAS,IACd,CAAA,EAAA,CAAA;AAAA,KAEN,CAAA;AACD,IAAI,IAAA,IAAA,CAAK,EAAM,IAAA,CAAA,CAAE,GAAK,EAAA;AACpB,MAAM,MAAA,CAAA,GAAI,KAAK,GAAI,EAAA;AACnB,MAAK,IAAA,CAAA,EAAA,CAAG,QAAQ,IAAK,CAAA;AAAA,QACnB,CAAA;AAAA,QACA,OAAO,CAAE,CAAA;AAAA,OACV,CAAA;AACD,MAAK,IAAA,CAAA,EAAA,CAAG,OAAO,CAAE,CAAA,GAAA;AACjB,MAAA,IAAA,CAAK,GAAG,KAAS,IAAA,CAAA;AACjB,MAAK,IAAA,CAAA,EAAA,CAAG,MAAM,IAAK,CAAA,GAAA,CAAI,KAAK,EAAG,CAAA,GAAA,EAAK,EAAE,GAAG,CAAA;AACzC,MAAM,MAAA,GAAA,GAAM,KAAK,QAAS,CAAA,SAAA;AAC1B,MAAI,IAAA,GAAA,OAAU,GAAI,CAAA;AAAA,QAChB,SAAA,EAAW,iCACN,GADM,CAAA,EAAA;AAAA,UAET,KAAA,EAAO,KAAK,KAAM,CAAA,IAAA,CAAK,GAAG,GAAM,GAAA,IAAA,CAAK,GAAG,KAAK,CAAA;AAAA,UAC7C,KAAA,EAAO,KAAK,EAAG,CAAA;AAAA,SACjB;AAAA,OACD,CAAA;AAAA;AACH;AACF;AAAA,EAGA,eAAe,WAA2B,EAAA;AACxC,IAAA,IAAA,CAAK,EAAK,GAAA;AAAA,MACR,SAAS,EAAC;AAAA,MACV,GAAK,EAAA,CAAA;AAAA,MACL,KAAO,EAAA,CAAA;AAAA,MACP,GAAK,EAAA;AAAA,KACP;AACA,IAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACP,SAAW,EAAA;AAAA,QACT,SAAA,EAAW,KAAK,GAAI,EAAA;AAAA,QACpB;AAAA;AACF,KACD,CAAA;AAAA;AACH;AAAA,EAGA,MAAM,aAAkD,GAAA;AACtD,IAAM,MAAA,GAAA,GAAM,KAAK,QAAS,CAAA,SAAA;AAC1B,IAAA,MAAM,KAAK,IAAK,CAAA,EAAA;AAChB,IAAA,IAAA,CAAK,EAAK,GAAA,IAAA;AACV,IAAA,IAAA,CAAK,GAAI,CAAA;AAAA,MACP,SAAW,EAAA;AAAA,KACZ,CAAA;AACD,IAAA,MAAM,SAAS,IAAK,CAAA,IAAA;AACpB,IAAI,IAAA,CAAC,OAAO,CAAC,EAAA,IAAM,CAAC,EAAG,CAAA,KAAA,IAAS,CAAC,MAAA,EAAe,OAAA,IAAA;AAChD,IAAM,MAAA,GAAA,GAAM,KAAK,GAAI,EAAA;AACrB,IAAA,MAAM,OAA4B,GAAA;AAAA,MAChC,IAAM,EAAA,YAAA;AAAA,MACN,IAAI,SAAU,CAAA,MAAA,CAAO,EAAI,EAAA,YAAA,EAAc,IAAI,SAAS,CAAA;AAAA,MACpD,IAAI,GAAI,CAAA,SAAA;AAAA,MACR,GAAA;AAAA,MACA,UAAU,MAAO,CAAA,EAAA;AAAA,MACjB,YAAY,MAAO,CAAA,IAAA;AAAA,MACnB,aAAa,GAAI,CAAA,WAAA;AAAA,MACjB,OAAO,IAAK,CAAA,KAAA,CAAM,EAAG,CAAA,GAAA,GAAM,GAAG,KAAK,CAAA;AAAA,MACnC,OAAO,EAAG,CAAA,GAAA;AAAA,MACV,OAAA,EAAS,WAAY,CAAA,EAAA,CAAG,OAAO;AAAA,KACjC;AACA,IAAA,MAAM,IAAK,CAAA,IAAA,CAAK,CAAC,OAAO,CAAC,CAAA;AACzB,IAAO,OAAA,OAAA;AAAA;AACT;AAAA,EAGA,MAAM,QAA0B,GAAA;AAC9B,IAAM,MAAA,IAAA,GAAO,KAAK,QAAS,CAAA,IAAA;AAC3B,IAAA,MAAM,SAAS,IAAK,CAAA,IAAA;AACpB,IAAA,IAAI,CAAC,MAAA,IAAA,CAAU,IAAM,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,IAAA,MAAS,MAAW,EAAA;AACzC,IAAM,MAAA,EAAA,GAAK,KAAK,GAAI,EAAA;AACpB,IAAM,MAAA,IAAA,CAAK,KAAK,CAAC,cAAA,CAAA;AAAA,MACf,IAAM,EAAA,MAAA;AAAA,MACN,IAAI,SAAU,CAAA,MAAA,CAAO,IAAI,MAAQ,EAAA,EAAA,EAAI,KAAK,IAAI,CAAA;AAAA,MAC9C,EAAA;AAAA,MACA,UAAU,MAAO,CAAA,EAAA;AAAA,MACjB,YAAY,MAAO,CAAA,IAAA;AAAA,MACnB,MAAM,IAAK,CAAA;AAAA,KACP,EAAA,IAAA,CAAK,UAAU,MAAY,GAAA;AAAA,MAC7B,OAAO,IAAK,CAAA;AAAA,KACd,GAAI,EAAC,CACN,CAAC,CAAA;AAAA;AACJ,EACQ,YAAe,GAAA;AAzXzB,IAAA,IAAA,EAAA;AA0XI,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,WAAL,IAAa,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,EAAA;AACb,IAAA,IAAA,CAAK,MAAS,GAAA,IAAA;AACd,IAAA,MAAM,OAAO,IAAK,CAAA,IAAA;AAClB,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA;AACZ,IAAA,IAAI,IAAK,CAAA,EAAA,EAAS,KAAA,IAAA,CAAK,aAAc,EAAA;AACrC,IAAM,MAAA,CAAA,GAAI,KAAK,QAAS,CAAA,KAAA;AACxB,IAAI,IAAA,CAAA,CAAE,IAAS,KAAA,WAAA,IAAe,IAAM,EAAA;AAElC,MAAA,IAAA,CAAK,GAAI,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,IAAM,EAAA,OAAA;AAAA,UACN,MAAQ,EAAA;AAAA,YACN,IAAI,IAAK,CAAA,EAAA;AAAA,YACT,MAAM,IAAK,CAAA;AAAA;AACb,SACF;AAAA,QACA,IAAM,EAAA;AAAA,OACP,CAAA;AAAA;AACH;AACF,EACQ,SAAY,GAAA;AA9YtB,IAAA,IAAA,EAAA;AA+YI,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,QAAL,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,IAAA,IAAA,CAAK,QAAW,GAAA,IAAA;AAChB,IAAA,IAAI,IAAK,CAAA,SAAA,EAAwB,YAAA,CAAA,IAAA,CAAK,SAAS,CAAA;AAC/C,IAAA,IAAA,CAAK,SAAY,GAAA,IAAA;AAAA;AACnB;AAAA,EAGA,MAAM,KAAuB,GAAA;AAtZ/B,IAAA,IAAA,EAAA;AAuZI,IAAA,IAAI,IAAK,CAAA,EAAA,EAAU,MAAA,IAAA,CAAK,aAAc,EAAA;AACtC,IAAA,IAAA,CAAK,SAAU,EAAA;AACf,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,WAAL,IAAa,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,EAAA;AACb,IAAA,IAAA,CAAK,MAAS,GAAA,IAAA;AACd,IAAA,MAAM,OAAO,IAAK,CAAA,IAAA;AAClB,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA;AACZ,IAAA,IAAA,CAAK,MAAS,GAAA,IAAA;AACd,IAAA,OAAM,IAAM,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,KAAA,EAAA,CAAA;AAAA;AAEhB;AACA,SAAS,mBAAmB,GAAsB,EAAA;AAEhD,EAAI,IAAA,GAAA,YAAe,SAAS,gCAAiC,CAAA,IAAA,CAAK,IAAI,OAAO,CAAA,SAAU,GAAI,CAAA,OAAA;AAC3F,EAAA,OAAO,iBAAiB,GAAG,CAAA;AAC7B"}
1
+ {"version":3,"file":"session.js","sources":["../../../src/features/devices/session.ts"],"sourcesContent":["/**\n * One \"take a reading\" from start to end, for the screen: is Bluetooth on and\n * allowed, find the device (or the one already paired), connect, run its\n * driver, keep what it measures, and end cleanly when it goes to sleep (a\n * scale switches off seconds after a weighing; that is the normal end, not an\n * error).\n *\n * Heart-rate straps and continuous oximeters stream: the person starts and\n * stops a session (heart rate) or saves the value they see (oxygen).\n *\n * Plain class with injected transport and store, like the other stores: the\n * screen subscribes with useSyncExternalStore, tests drive it with fakes.\n */\nimport type { TimedValue } from '../health/model';\nimport { deviceKind, type DeviceKindId } from './catalog';\nimport { describeBleError, type BleTransport, type ConnectedLink, type FoundDevice, type RadioState } from './link';\nimport { detectBrand } from './brands';\nimport type { DeviceStore } from './deviceStore';\nimport { startDriver, type DriverHandle, type LiveValue, type PersonFacts } from './drivers';\nimport { computeBodyComposition } from './bodyComposition';\nimport { readingId, thinSamples, type DeviceReading, type HeartRateSession } from './readings';\n\nexport type SessionState =\n | { step: 'starting' }\n | { step: 'unavailable'; reason: string }\n | { step: 'radio'; radio: Exclude<RadioState, 'ready'> }\n | { step: 'scanning'; found: FoundDevice[]; hint?: string }\n | { step: 'connecting'; device: FoundDevice }\n | { step: 'connected'; device: { id: string; name: string } }\n | { step: 'ended'; device: { id: string; name: string } }\n | { step: 'error'; message: string };\n\nexport interface SessionSnapshot {\n state: SessionState;\n kind: DeviceKindId;\n /** What this session measured, newest first. */\n readings: DeviceReading[];\n live?: LiveValue;\n recording?: { startedAt: number; workoutType: string; avgHr?: number; maxHr?: number };\n notices: string[];\n}\n\nexport interface SessionDeps {\n transport: BleTransport | null;\n store: Pick<DeviceStore, 'pair' | 'addReadings' | 'saveScaleUser' | 'person' | 'getSnapshot'>;\n kind: DeviceKindId;\n /** Reconnect to this paired device instead of offering a list. */\n deviceId?: string;\n now?: () => number;\n}\n\n/** Scanning this long without finding anything: tell the person how to wake it. */\nexport const SCAN_HINT_MS = 20_000;\n\nfunction ageFrom(birthDate: string | undefined, now: number): number | undefined {\n if (!birthDate) return undefined;\n const t = Date.parse(`${birthDate}T00:00:00Z`);\n return Number.isFinite(t) ? Math.floor((now - t) / (365.25 * 86_400_000)) : undefined;\n}\n\n/**\n * Fill in the full body composition for a body reading once the scale has given\n * weight and body fat and the person's height/age/sex are known. Other readings\n * pass through unchanged.\n */\nfunction enrichWithComposition(reading: DeviceReading, facts: PersonFacts): DeviceReading {\n if (reading.kind !== 'body' || reading.weightKg === undefined || reading.bodyFatPct === undefined) {\n return reading;\n }\n if (!facts.heightCm || facts.age === undefined) return reading;\n const composition = computeBodyComposition({\n weightKg: reading.weightKg,\n bodyFatPct: reading.bodyFatPct,\n heightCm: facts.heightCm,\n age: facts.age,\n sex: facts.sex ?? 'unspecified',\n impedanceOhm: reading.impedanceOhm,\n });\n return {\n ...reading,\n bmi: reading.bmi ?? composition.bmi,\n leanMassKg: reading.leanMassKg ?? composition.leanMassKg,\n composition,\n };\n}\n\nexport class DeviceSession {\n private snapshot: SessionSnapshot;\n\n private listeners = new Set<() => void>();\n\n private stopScan: (() => void) | null = null;\n\n private link: ConnectedLink | null = null;\n\n private driver: DriverHandle | null = null;\n\n private hintTimer: ReturnType<typeof setTimeout> | null = null;\n\n private hr: { samples: TimedValue[]; sum: number; count: number; max: number } | null = null;\n\n private closed = false;\n\n constructor(private readonly deps: SessionDeps) {\n this.snapshot = { state: { step: 'starting' }, kind: deps.kind, readings: [], notices: [] };\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): SessionSnapshot => this.snapshot;\n\n private now(): number {\n return this.deps.now ? this.deps.now() : Date.now();\n }\n\n private set(patch: Partial<SessionSnapshot>) {\n if (this.closed) return;\n this.snapshot = { ...this.snapshot, ...patch };\n this.listeners.forEach((l) => l());\n }\n\n async start(): Promise<void> {\n const { transport } = this.deps;\n if (!transport) {\n this.set({\n state: { step: 'unavailable', reason: 'Bluetooth devices need the latest version of the Yantra app.' },\n });\n return;\n }\n if (!(await transport.requestPermissions())) {\n this.set({ state: { step: 'radio', radio: 'unauthorized' } });\n return;\n }\n const radio = await transport.radio();\n if (radio !== 'ready' && radio !== 'unknown') {\n this.set({ state: { step: 'radio', radio } });\n return;\n }\n this.scan();\n }\n\n /** Back to looking for the device (after the radio came on, or to measure again). */\n scan(): void {\n const { transport } = this.deps;\n if (!transport || this.closed) return;\n this.stopScan?.();\n this.set({ state: { step: 'scanning', found: [] } });\n this.hintTimer = setTimeout(() => {\n const s = this.snapshot.state;\n if (s.step === 'scanning' && !s.found.length) {\n this.set({ state: { ...s, hint: deviceKind(this.deps.kind).steps[0] } });\n }\n }, SCAN_HINT_MS);\n const kind = this.deps.kind;\n this.stopScan = transport.scan(\n {\n services: deviceKind(kind).services,\n // Brand devices do not advertise a standard service: recognise this kind of them.\n match: (adv) => {\n const brand = detectBrand(adv);\n return brand && brand.kind === kind ? brand : undefined;\n },\n },\n (found) => {\n const s = this.snapshot.state;\n if (s.step !== 'scanning') return;\n if (this.deps.deviceId && found.id === this.deps.deviceId) {\n void this.pick(found);\n return;\n }\n if (this.deps.deviceId) return;\n this.set({\n state: {\n ...s,\n hint: undefined,\n found: [...s.found, found].sort((a, b) => (b.rssi ?? -999) - (a.rssi ?? -999)),\n },\n });\n },\n (message) => this.set({ state: { step: 'error', message } }),\n );\n }\n\n async pick(found: FoundDevice): Promise<void> {\n const { transport, store } = this.deps;\n if (!transport) return;\n this.clearScan();\n this.set({ state: { step: 'connecting', device: found } });\n try {\n const link = await transport.connect(found.id, found.name, () => this.onDisconnect());\n this.link = link;\n const paired = store.getSnapshot().devices.find((d) => d.id === link.id);\n const person = await store.person();\n const facts: PersonFacts = {\n age: ageFrom(person?.birthDate, this.now()),\n sex: person?.sex,\n heightCm: person?.heightCm,\n birthDate: person?.birthDate,\n weightKg: paired?.lastWeightKg,\n };\n this.driver = await startDriver(this.deps.kind, link, {\n now: () => this.now(),\n person: facts,\n identity: found.protocol\n ? {\n protocol: found.protocol,\n mac: found.mac,\n deviceType: found.deviceType,\n model: found.model,\n kind: found.kind,\n }\n : undefined,\n scaleUser: paired?.scaleUser,\n saveScaleUser: (user) => store.saveScaleUser(link.id, user),\n onReading: (r) => void this.keep([enrichWithComposition(r, facts)]),\n onLive: (v) => this.onLive(v),\n onNotice: (m) => this.set({ notices: [...this.snapshot.notices, m] }),\n });\n await store.pair({\n id: link.id,\n name: link.name,\n kind: this.deps.kind,\n ...(found.protocol ? { protocol: found.protocol } : {}),\n });\n this.set({ state: { step: 'connected', device: { id: link.id, name: link.name } } });\n } catch (err) {\n await this.link?.close();\n this.link = null;\n this.set({ state: { step: 'error', message: describeErrorOrOwn(err) } });\n }\n }\n\n private async keep(readings: DeviceReading[]): Promise<void> {\n const fresh = await this.deps.store.addReadings(readings);\n if (fresh.length) this.set({ readings: [...fresh.reverse(), ...this.snapshot.readings] });\n }\n\n private onLive(v: LiveValue) {\n this.set({ live: { ...this.snapshot.live, ...v } });\n if (this.hr && v.bpm) {\n const t = this.now();\n this.hr.samples.push({ t, value: v.bpm });\n this.hr.sum += v.bpm;\n this.hr.count += 1;\n this.hr.max = Math.max(this.hr.max, v.bpm);\n const rec = this.snapshot.recording;\n if (rec)\n this.set({ recording: { ...rec, avgHr: Math.round(this.hr.sum / this.hr.count), maxHr: this.hr.max } });\n }\n }\n\n /** Heart rate: start recording a session of the given kind (run, walk, cycle, strength ...). */\n startRecording(workoutType: string): void {\n this.hr = { samples: [], sum: 0, count: 0, max: 0 };\n this.set({ recording: { startedAt: this.now(), workoutType } });\n }\n\n /** Heart rate: end the session and keep it. Nothing is kept for a session with no heart rate. */\n async stopRecording(): Promise<HeartRateSession | null> {\n const rec = this.snapshot.recording;\n const hr = this.hr;\n this.hr = null;\n this.set({ recording: undefined });\n const device = this.link;\n if (!rec || !hr || !hr.count || !device) return null;\n const end = this.now();\n const session: HeartRateSession = {\n kind: 'heart-rate',\n id: readingId(device.id, 'heart-rate', rec.startedAt),\n at: rec.startedAt,\n end,\n deviceId: device.id,\n deviceName: device.name,\n workoutType: rec.workoutType,\n avgHr: Math.round(hr.sum / hr.count),\n maxHr: hr.max,\n samples: thinSamples(hr.samples),\n };\n await this.keep([session]);\n return session;\n }\n\n /** Continuous oximeter: keep the value on screen as a reading. */\n async saveLive(): Promise<void> {\n const live = this.snapshot.live;\n const device = this.link;\n if (!device || live?.spo2 === undefined) return;\n const at = this.now();\n await this.keep([\n {\n kind: 'spo2',\n id: readingId(device.id, 'spo2', at, live.spo2),\n at,\n deviceId: device.id,\n deviceName: device.name,\n spo2: live.spo2,\n ...(live.pulse !== undefined ? { pulse: live.pulse } : {}),\n },\n ]);\n }\n\n private onDisconnect() {\n this.driver?.stop();\n this.driver = null;\n const link = this.link;\n this.link = null;\n if (this.hr) void this.stopRecording();\n const s = this.snapshot.state;\n if (s.step === 'connected' && link) {\n // A scale or cuff switches off after measuring: the normal end.\n this.set({ state: { step: 'ended', device: { id: link.id, name: link.name } }, live: undefined });\n }\n }\n\n private clearScan() {\n this.stopScan?.();\n this.stopScan = null;\n if (this.hintTimer) clearTimeout(this.hintTimer);\n this.hintTimer = null;\n }\n\n /** Leave: finish what was being assembled, stop scanning, disconnect. */\n async close(): Promise<void> {\n if (this.hr) await this.stopRecording();\n this.clearScan();\n this.driver?.stop();\n this.driver = null;\n const link = this.link;\n this.link = null;\n this.closed = true;\n await link?.close();\n }\n}\n\nfunction describeErrorOrOwn(err: unknown): string {\n // The drivers' own messages are already in plain words (\"does not send weight the standard way\").\n if (err instanceof Error && /standard way|does not know how/.test(err.message)) return err.message;\n return describeBleError(err);\n}\n"],"names":["_a"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {jsxs,jsx,Fragment}from'react/jsx-runtime';import React__default,{useState,useMemo,useCallback,useEffect,useRef}from'react';import {BackHandler,StyleSheet,View,Pressable,ActivityIndicator,ScrollView,Linking,Alert,Animated,Easing,Platform}from'react-native';import {Ionicons}from'@expo/vector-icons';import {Text}from'@admin-layout/gluestack-ui-mobile';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {mobileColors,mobileTokens}from'../../theme/mobileTokens.js';import {useAppTheme}from'../../theme/AppThemeProvider.js';import {deviceKind,DEVICE_KINDS}from'../../features/devices/catalog.js';import {useDevices,useDeviceSession,platformWriter,deviceStore}from'../../features/devices/devices.js';import {describeReading}from'../../features/devices/readings.js';import {useHealthSync}from'../../features/health/healthSync.js';var __defProp = Object.defineProperty;
1
+ import {jsxs,jsx,Fragment}from'react/jsx-runtime';import React__default,{useState,useMemo,useCallback,useEffect,useRef}from'react';import {BackHandler,StyleSheet,View,Pressable,ActivityIndicator,ScrollView,Linking,Alert,Animated,Easing,Platform}from'react-native';import {Ionicons}from'@expo/vector-icons';import {Text}from'@admin-layout/gluestack-ui-mobile';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {mobileColors,mobileTokens}from'../../theme/mobileTokens.js';import {useAppTheme}from'../../theme/AppThemeProvider.js';import {deviceKind,DEVICE_KINDS}from'../../features/devices/catalog.js';import {useDevices,useDeviceSession,platformWriter,deviceStore}from'../../features/devices/devices.js';import {describeReading}from'../../features/devices/readings.js';import {compositionRows}from'../../features/devices/bodyComposition.js';import {useHealthSync}from'../../features/health/healthSync.js';var __defProp = Object.defineProperty;
2
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
4
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -305,6 +305,53 @@ const styles = StyleSheet.create({
305
305
  fontSize: 14,
306
306
  marginTop: 2
307
307
  },
308
+ measureBox: {
309
+ alignItems: "center",
310
+ paddingVertical: 24,
311
+ gap: 6
312
+ },
313
+ measureRing: {
314
+ position: "absolute",
315
+ top: 24,
316
+ width: 176,
317
+ height: 176,
318
+ borderRadius: 88,
319
+ borderWidth: 2
320
+ },
321
+ measureCore: {
322
+ width: 176,
323
+ height: 176,
324
+ borderRadius: 88,
325
+ alignItems: "center",
326
+ justifyContent: "center",
327
+ marginBottom: 12
328
+ },
329
+ measureWeight: {
330
+ fontSize: 44,
331
+ fontWeight: "700"
332
+ },
333
+ measureUnit: {
334
+ fontSize: 18,
335
+ fontWeight: "600"
336
+ },
337
+ compositionGrid: {
338
+ flexDirection: "row",
339
+ flexWrap: "wrap",
340
+ marginTop: 10,
341
+ rowGap: 10
342
+ },
343
+ compositionItem: {
344
+ width: "33.33%",
345
+ paddingRight: 8
346
+ },
347
+ compositionLabel: {
348
+ fontSize: 12
349
+ },
350
+ compositionValue: {
351
+ fontSize: 15,
352
+ fontWeight: "600",
353
+ marginTop: 1
354
+ },
308
355
  savedLine: {
309
356
  flexDirection: "row",
310
357
  alignItems: "center",
@@ -567,7 +614,15 @@ function ReadingsCard({
567
614
  }], children: whenLabel(r.at, now) }),
568
615
  r.kind === "blood-pressure" && ((_a = r.problems) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(Text, { style: [styles.readingNote, {
569
616
  color: colors.warningText
570
- }], children: r.problems.join(" ") }) : null
617
+ }], children: r.problems.join(" ") }) : null,
618
+ r.kind === "body" && r.composition ? /* @__PURE__ */ jsx(View, { style: styles.compositionGrid, children: compositionRows(r.composition, units).map((m) => /* @__PURE__ */ jsxs(View, { style: styles.compositionItem, children: [
619
+ /* @__PURE__ */ jsx(Text, { style: [styles.compositionLabel, {
620
+ color: colors.textMuted
621
+ }], children: m.label }),
622
+ /* @__PURE__ */ jsx(Text, { style: [styles.compositionValue, {
623
+ color: colors.text
624
+ }], children: m.value })
625
+ ] }, m.label)) }) : null
571
626
  ] })
572
627
  ] }, r.id);
573
628
  }) })
@@ -772,10 +827,151 @@ function PickKind({
772
827
  ] }, k.id)) })
773
828
  ] });
774
829
  }
830
+ function formatWeight(kg, units) {
831
+ if (kg === void 0) return "--";
832
+ const v = units === "imperial" ? kg / 0.45359237 : kg;
833
+ return (Math.round(v * 10) / 10).toFixed(1);
834
+ }
835
+ function ScaleMeasuring({
836
+ colors,
837
+ live,
838
+ units
839
+ }) {
840
+ const pulse = useRef(new Animated.Value(0)).current;
841
+ useEffect(() => {
842
+ const loop = Animated.loop(Animated.timing(pulse, {
843
+ toValue: 1,
844
+ duration: 1400,
845
+ easing: Easing.out(Easing.ease),
846
+ useNativeDriver: true
847
+ }));
848
+ loop.start();
849
+ return () => loop.stop();
850
+ }, [pulse]);
851
+ const ringScale = pulse.interpolate({
852
+ inputRange: [0, 1],
853
+ outputRange: [0.9, 1.5]
854
+ });
855
+ const ringOpacity = pulse.interpolate({
856
+ inputRange: [0, 1],
857
+ outputRange: [0.5, 0]
858
+ });
859
+ const unitLabel = units === "imperial" ? "lb" : "kg";
860
+ return /* @__PURE__ */ jsxs(View, { style: styles.measureBox, children: [
861
+ /* @__PURE__ */ jsx(Animated.View, { style: [styles.measureRing, {
862
+ borderColor: colors.primary,
863
+ opacity: ringOpacity,
864
+ transform: [{
865
+ scale: ringScale
866
+ }]
867
+ }], accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" }),
868
+ /* @__PURE__ */ jsx(View, { style: [styles.measureCore, {
869
+ backgroundColor: colors.primarySoft
870
+ }], children: /* @__PURE__ */ jsxs(Text, { style: [styles.measureWeight, {
871
+ color: colors.text
872
+ }], accessibilityLabel: `${formatWeight(live.weightKg, units)} ${unitLabel}`, children: [
873
+ formatWeight(live.weightKg, units),
874
+ /* @__PURE__ */ jsxs(Text, { style: [styles.measureUnit, {
875
+ color: colors.textMuted
876
+ }], children: [
877
+ " ",
878
+ unitLabel
879
+ ] })
880
+ ] }) }),
881
+ /* @__PURE__ */ jsx(Text, { style: [styles.statusTitle, {
882
+ color: colors.text
883
+ }], children: "Measuring" }),
884
+ /* @__PURE__ */ jsx(Text, { style: [styles.statusBody, {
885
+ color: colors.textMuted
886
+ }], children: "Stand still, barefoot, until it settles." })
887
+ ] });
888
+ }
889
+ function BrandLive({
890
+ kind,
891
+ colors,
892
+ live,
893
+ units
894
+ }) {
895
+ var _a, _b, _c;
896
+ const items = [];
897
+ const round1 = (n) => Math.round(n * 10) / 10;
898
+ if (kind === "kitchen-scale") items.push({
899
+ label: "Weight",
900
+ value: `${Math.round((_a = live.grams) != null ? _a : 0)} g`
901
+ });
902
+ if (kind === "tape") {
903
+ const cm = (_b = live.lengthCm) != null ? _b : 0;
904
+ items.push({
905
+ label: live.bodyPart ? live.bodyPart.replace(/_/g, " ") : "Length",
906
+ value: units === "imperial" ? `${round1(cm / 2.54)} in` : `${round1(cm)} cm`
907
+ });
908
+ }
909
+ if (kind === "jump-rope") {
910
+ items.push({
911
+ label: "Jumps",
912
+ value: String((_c = live.jumps) != null ? _c : 0)
913
+ });
914
+ if (live.elapsedS !== void 0) items.push({
915
+ label: "Time",
916
+ value: clockOf(live.elapsedS)
917
+ });
918
+ }
919
+ if (kind === "treadmill") {
920
+ if (live.speedKmh !== void 0) items.push({
921
+ label: "Speed",
922
+ value: `${round1(live.speedKmh)} km/h`
923
+ });
924
+ if (live.distanceM !== void 0) items.push({
925
+ label: "Distance",
926
+ value: `${round1(live.distanceM / 1e3)} km`
927
+ });
928
+ if (live.kcal !== void 0) items.push({
929
+ label: "Calories",
930
+ value: `${Math.round(live.kcal)} kcal`
931
+ });
932
+ if (live.elapsedS !== void 0) items.push({
933
+ label: "Time",
934
+ value: clockOf(live.elapsedS)
935
+ });
936
+ }
937
+ if (kind === "ring") {
938
+ if (live.bpm !== void 0) items.push({
939
+ label: "Heart rate",
940
+ value: `${live.bpm} bpm`
941
+ });
942
+ if (live.spo2 !== void 0) items.push({
943
+ label: "Blood oxygen",
944
+ value: `${live.spo2}%`
945
+ });
946
+ if (live.skinTempC !== void 0) items.push({
947
+ label: "Skin temp",
948
+ value: `${round1(live.skinTempC)} \xB0C`
949
+ });
950
+ if (live.steps !== void 0) items.push({
951
+ label: "Steps",
952
+ value: String(live.steps)
953
+ });
954
+ }
955
+ if (live.battery !== void 0) items.push({
956
+ label: "Battery",
957
+ value: `${live.battery}%`
958
+ });
959
+ return /* @__PURE__ */ jsx(View, { style: [styles.card, styles.livePanel, {
960
+ backgroundColor: colors.surface
961
+ }], children: /* @__PURE__ */ jsx(View, { style: styles.compositionGrid, children: items.map((m) => /* @__PURE__ */ jsxs(View, { style: styles.compositionItem, children: [
962
+ /* @__PURE__ */ jsx(Text, { style: [styles.compositionLabel, {
963
+ color: colors.textMuted
964
+ }], children: m.label }),
965
+ /* @__PURE__ */ jsx(Text, { style: [styles.compositionValue, {
966
+ color: colors.text
967
+ }], children: m.value })
968
+ ] }, m.label)) }) });
969
+ }
775
970
  function LivePanel({
776
971
  kind,
777
972
  colors,
778
973
  live,
974
+ units,
779
975
  recording,
780
976
  connected,
781
977
  onStart,
@@ -784,6 +980,12 @@ function LivePanel({
784
980
  }) {
785
981
  var _a, _b, _c, _d, _e;
786
982
  const [type, setType] = useState("run");
983
+ if (kind === "scale") {
984
+ return /* @__PURE__ */ jsx(ScaleMeasuring, { colors, live, units });
985
+ }
986
+ if (kind === "kitchen-scale" || kind === "tape" || kind === "jump-rope" || kind === "treadmill" || kind === "ring") {
987
+ return /* @__PURE__ */ jsx(BrandLive, { kind, colors, live, units });
988
+ }
787
989
  const [, tick] = useState(0);
788
990
  useEffect(() => {
789
991
  if (!recording) return void 0;
@@ -943,7 +1145,7 @@ function Measure({
943
1145
  "."
944
1146
  ] })
945
1147
  ] }) : null,
946
- (state.step === "connected" || state.step === "ended") && live ? /* @__PURE__ */ jsx(LivePanel, { kind, colors, live, recording, connected: state.step === "connected", onStart: (type) => session == null ? void 0 : session.startRecording(type), onStop: () => {
1148
+ (state.step === "connected" || state.step === "ended") && live ? /* @__PURE__ */ jsx(LivePanel, { kind, colors, live, units, recording, connected: state.step === "connected", onStart: (type) => session == null ? void 0 : session.startRecording(type), onStop: () => {
947
1149
  void (session == null ? void 0 : session.stopRecording());
948
1150
  }, onSave: () => {
949
1151
  void (session == null ? void 0 : session.saveLive());
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/screens/Devices/index.tsx"],"sourcesContent":["/**\n * Devices: the Bluetooth health devices the person paired, and pairing a new\n * one. One route with its own small stack (home -> pick a kind -> measure, or\n * home -> a device -> measure), so the flow never leaves the screen:\n *\n * - home: the paired devices with their last reading, and \"Add a device\";\n * - pick: which kind of device (scale, blood pressure, heart rate ...);\n * - measure: how to wake it, the devices found nearby, connecting, waiting for\n * a measurement (or live heart rate / oxygen), and what it measured;\n * - device: its readings, take another, forget it.\n *\n * Only devices that speak the Bluetooth SIG health profiles pair here. A brand\n * scale with its own app (RENPHO, Withings ...) keeps that app; it writes to\n * Apple Health / Health Connect and Yantra reads it there, which the home says.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n ActivityIndicator,\n Alert,\n Animated,\n BackHandler,\n Easing,\n Linking,\n Platform,\n Pressable,\n ScrollView,\n StyleSheet,\n View,\n} from 'react-native';\nimport { Ionicons } from '@expo/vector-icons';\nimport { Text } from '@admin-layout/gluestack-ui-mobile';\nimport {\n CommonActions,\n useNavigation,\n useRoute,\n type NavigationProp,\n type ParamListBase,\n type RouteProp,\n} from '@react-navigation/native';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { mobileColors, mobileTokens } from '../../theme/mobileTokens';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport { DEVICE_KINDS, deviceKind, type DeviceKindId } from '../../features/devices/catalog';\nimport { deviceStore, platformWriter, useDeviceSession, useDevices } from '../../features/devices/devices';\nimport { describeReading, type DeviceReading } from '../../features/devices/readings';\nimport type { PairedDevice } from '../../features/devices/deviceStore';\nimport type { FoundDevice, RadioState } from '../../features/devices/link';\nimport { useHealthSync } from '../../features/health/healthSync';\n\ntype Colors = ReturnType<typeof mobileColors>;\ntype Glyph = keyof typeof Ionicons.glyphMap;\n/** `add`: open straight on \"Which device\" (the Fitness page's Add a device). */\ntype DevicesParams = { orgName?: string; add?: boolean } | undefined;\ntype Step =\n | { name: 'home' }\n | { name: 'pick' }\n | { name: 'measure'; kind: DeviceKindId; deviceId?: string }\n | { name: 'device'; id: string };\n\nconst IS_IOS = Platform.OS === 'ios';\n/** The app's surfaces are white on a white page in light mode; an edge keeps each card readable as one. */\nconst CARD_EDGE = 'rgba(148,163,184,0.3)';\nconst STORE_NAME = IS_IOS ? 'Apple Health' : 'Health Connect';\nconst WORKOUT_TYPES: Array<{ id: string; label: string }> = [\n { id: 'run', label: 'Run' },\n { id: 'walk', label: 'Walk' },\n { id: 'cycle', label: 'Ride' },\n { id: 'strength', label: 'Strength' },\n { id: 'hiit', label: 'HIIT' },\n { id: 'other', label: 'Other' },\n];\n\nconst styles = StyleSheet.create({\n safe: { flex: 1 },\n header: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingBottom: 8, minHeight: 52 },\n backCircle: {\n width: 40,\n height: 40,\n borderRadius: 20,\n alignItems: 'center',\n justifyContent: 'center',\n ...mobileTokens.shadow.card,\n },\n headerTitle: { flex: 1, textAlign: 'center', fontSize: 17, fontWeight: '600', marginHorizontal: 8 },\n headerSpacer: { width: 40, height: 40 },\n pressed: { opacity: 0.72 },\n loading: { marginTop: 48 },\n scroll: { paddingHorizontal: 16, paddingBottom: 40 },\n hero: { alignItems: 'center', paddingTop: 8, paddingBottom: 16, gap: 10 },\n heroIcon: { width: 64, height: 64, borderRadius: 32, alignItems: 'center', justifyContent: 'center' },\n heroTitle: { fontSize: 20, fontWeight: '700', textAlign: 'center' },\n heroBody: { fontSize: 15, lineHeight: 21, textAlign: 'center', paddingHorizontal: 8 },\n card: { borderRadius: 16, overflow: 'hidden', borderWidth: 1, borderColor: CARD_EDGE },\n secondaryCard: { marginTop: 20 },\n sectionTitle: {\n fontSize: 13,\n fontWeight: '600',\n letterSpacing: 0.4,\n marginTop: 24,\n marginBottom: 8,\n marginLeft: 16,\n },\n row: { flexDirection: 'row', alignItems: 'center', minHeight: 52, paddingHorizontal: 16, gap: 12 },\n rowLabelWide: { flex: 1, fontSize: 16 },\n rowLine: { height: StyleSheet.hairlineWidth, marginLeft: 16 },\n deviceRow: { flexDirection: 'row', alignItems: 'center', minHeight: 64, paddingHorizontal: 16, gap: 12 },\n deviceText: { flex: 1, minWidth: 0 },\n deviceName: { fontSize: 16, fontWeight: '600' },\n deviceMeta: { fontSize: 14, marginTop: 2 },\n kindIcon: { alignItems: 'center', justifyContent: 'center' },\n question: { fontSize: 22, fontWeight: '700', textAlign: 'center', marginTop: 8, marginBottom: 20, lineHeight: 28 },\n kindList: { gap: 10 },\n kindCard: {\n flexDirection: 'row',\n alignItems: 'center',\n borderRadius: 16,\n padding: 14,\n gap: 14,\n borderWidth: 1,\n borderColor: CARD_EDGE,\n },\n kindTitle: { fontSize: 16, fontWeight: '600' },\n center: { alignItems: 'center', paddingTop: 24, gap: 12 },\n statusTitle: { fontSize: 19, fontWeight: '700', textAlign: 'center', marginTop: 4 },\n statusBody: { fontSize: 15, lineHeight: 21, textAlign: 'center', paddingHorizontal: 8 },\n guidance: { marginTop: 16, paddingVertical: 8 },\n guidanceRow: { flexDirection: 'row', alignItems: 'flex-start', paddingHorizontal: 16, paddingVertical: 8, gap: 12 },\n stepDot: { width: 24, height: 24, borderRadius: 12, alignItems: 'center', justifyContent: 'center', marginTop: 1 },\n stepNumber: { fontSize: 13, fontWeight: '700' },\n guidanceText: { flex: 1, fontSize: 15, lineHeight: 22 },\n pulseBox: {\n alignSelf: 'center',\n width: 120,\n height: 120,\n alignItems: 'center',\n justifyContent: 'center',\n marginTop: 16,\n },\n pulseRing: { position: 'absolute', width: 64, height: 64, borderRadius: 32 },\n pulseCore: { width: 64, height: 64, borderRadius: 32, alignItems: 'center', justifyContent: 'center' },\n signal: { flexDirection: 'row', alignItems: 'flex-end', gap: 2, height: 16 },\n signalBar: { width: 4, borderRadius: 1 },\n livePanel: { alignItems: 'center', padding: 20, marginTop: 16, gap: 12 },\n liveValue: { fontSize: 56, fontWeight: '700', fontVariant: ['tabular-nums'] },\n liveUnit: { fontSize: 18, fontWeight: '500' },\n liveMeta: { fontSize: 15, fontVariant: ['tabular-nums'] },\n chips: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'center', gap: 8 },\n chip: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 14, paddingVertical: 8 },\n chipLabel: { fontSize: 14, fontWeight: '600' },\n readingRow: { paddingHorizontal: 16, paddingVertical: 12, gap: 2 },\n readingValue: { fontSize: 16, fontWeight: '600' },\n readingWhen: { fontSize: 14 },\n readingNote: { fontSize: 14, marginTop: 2 },\n savedLine: { flexDirection: 'row', alignItems: 'center', gap: 8, marginTop: 12, marginHorizontal: 4 },\n savedBlock: { marginTop: 12, gap: 10 },\n savedText: { flex: 1, fontSize: 14, lineHeight: 20 },\n notice: { flexDirection: 'row', borderRadius: 14, padding: 12, marginTop: 12, gap: 8 },\n noticeIcon: { marginTop: 1 },\n noticeText: { flex: 1, fontSize: 14, lineHeight: 20 },\n actions: { marginTop: 20, gap: 10, alignItems: 'stretch' },\n actionHint: { fontSize: 15, lineHeight: 21, textAlign: 'center' },\n primary: {\n backgroundColor: mobileTokens.color.primary,\n borderRadius: 14,\n minHeight: 50,\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 18,\n alignSelf: 'stretch',\n },\n primaryLabel: { color: '#fff', fontSize: 16, fontWeight: '600' },\n secondary: {\n borderRadius: 14,\n minHeight: 48,\n alignItems: 'center',\n justifyContent: 'center',\n borderWidth: 1,\n paddingHorizontal: 18,\n },\n secondaryLabel: { fontSize: 16, fontWeight: '600' },\n footnote: { fontSize: 13, lineHeight: 18, marginTop: 16, marginHorizontal: 16 },\n linkRow: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n marginTop: 10,\n marginHorizontal: 16,\n alignSelf: 'flex-start',\n },\n link: { fontSize: 14, fontWeight: '600' },\n});\n\nfunction stepTitle(step: Step, paired: PairedDevice[]): string {\n switch (step.name) {\n case 'pick':\n return 'Add a device';\n case 'measure':\n return deviceKind(step.kind).title;\n case 'device':\n return paired.find((d) => d.id === step.id)?.name ?? 'Device';\n default:\n return 'Devices';\n }\n}\n\n/** What to say when the radio is not ready to scan. */\nfunction radioCopy(radio: RadioState): { title: string; body: string } {\n if (radio === 'off') return { title: 'Turn on Bluetooth', body: 'Yantra finds your device over Bluetooth.' };\n if (radio === 'unauthorized') {\n return {\n title: 'Allow Bluetooth for Yantra',\n body: 'Yantra needs Bluetooth to find and read your device. Turn it on for Yantra in Settings.',\n };\n }\n return { title: 'This phone has no Bluetooth Yantra can use', body: '' };\n}\n\n/** Bars for the signal strength of a device found nearby. */\nfunction signalBars(rssi: number | undefined): number {\n if (rssi === undefined) return 1;\n if (rssi > -60) return 3;\n if (rssi > -80) return 2;\n return 1;\n}\n\nfunction whenLabel(at: number, now: number): string {\n const d = new Date(at);\n const time = d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });\n const startOf = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const days = Math.round((startOf(new Date(now)) - startOf(d)) / 86_400_000);\n if (days === 0) return `Today, ${time}`;\n if (days === 1) return `Yesterday, ${time}`;\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n}\n\n/** \"Today, 7:31 AM\" wraps as one piece, never with \"AM\" alone on the next line. */\nfunction keepTogether(text: string): string {\n return text.replace(/\\s/g, '\\u00a0');\n}\n\nfunction clockOf(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${String(s).padStart(2, '0')}`;\n}\n\n// ------------------------------------------------------------------ Pieces\n\nfunction KindIcon({ kind, colors, large }: { kind: DeviceKindId; colors: Colors; large?: boolean }) {\n const size = large ? 48 : 36;\n return (\n <View\n style={[\n styles.kindIcon,\n { width: size, height: size, borderRadius: size / 2, backgroundColor: colors.primarySoft },\n ]}\n >\n <Ionicons name={deviceKind(kind).icon as Glyph} size={large ? 24 : 18} color={colors.primary} />\n </View>\n );\n}\n\n/** The Bluetooth mark with a ring that breathes while scanning. */\nfunction BluetoothPulse({ colors, active, connected }: { colors: Colors; active: boolean; connected?: boolean }) {\n const pulse = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n if (!active) return undefined;\n const loop = Animated.loop(\n Animated.timing(pulse, {\n toValue: 1,\n duration: 1600,\n easing: Easing.out(Easing.ease),\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [active, pulse]);\n const scale = pulse.interpolate({ inputRange: [0, 1], outputRange: [1, 1.9] });\n const opacity = pulse.interpolate({ inputRange: [0, 1], outputRange: [0.45, 0] });\n return (\n <View style={styles.pulseBox} accessibilityElementsHidden importantForAccessibility=\"no-hide-descendants\">\n {active ? (\n <Animated.View\n style={[styles.pulseRing, { backgroundColor: colors.primary, opacity, transform: [{ scale }] }]}\n />\n ) : null}\n <View style={[styles.pulseCore, { backgroundColor: connected ? colors.successText : colors.primary }]}>\n <Ionicons name={connected ? 'checkmark' : 'bluetooth'} size={28} color=\"#fff\" />\n </View>\n </View>\n );\n}\n\nfunction Notice({\n colors,\n tone,\n icon,\n text,\n}: {\n colors: Colors;\n tone: 'warning' | 'danger';\n icon: Glyph;\n text: string;\n}) {\n const bg = tone === 'danger' ? colors.dangerSoft : colors.warningSoft;\n const fg = tone === 'danger' ? colors.dangerText : colors.warningText;\n return (\n <View style={[styles.notice, { backgroundColor: bg }]} accessibilityRole=\"alert\">\n <Ionicons name={icon} size={18} color={fg} style={styles.noticeIcon} />\n <Text style={[styles.noticeText, { color: fg }]}>{text}</Text>\n </View>\n );\n}\n\nfunction PrimaryButton({ label, onPress }: { label: string; onPress: () => void }) {\n return (\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n style={({ pressed }) => [styles.primary, pressed && styles.pressed]}\n >\n <Text style={styles.primaryLabel}>{label}</Text>\n </Pressable>\n );\n}\n\nfunction SecondaryButton({ label, onPress, colors }: { label: string; onPress: () => void; colors: Colors }) {\n return (\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n style={({ pressed }) => [\n styles.secondary,\n { borderColor: colors.border, backgroundColor: colors.surface },\n pressed && styles.pressed,\n ]}\n >\n <Text style={[styles.secondaryLabel, { color: colors.text }]}>{label}</Text>\n </Pressable>\n );\n}\n\nfunction ReadingsCard({\n title,\n readings,\n colors,\n units,\n now,\n}: {\n title: string;\n readings: DeviceReading[];\n colors: Colors;\n units: 'metric' | 'imperial';\n now: number;\n}) {\n return (\n <>\n <Text style={[styles.sectionTitle, { color: colors.textMuted }]}>{title}</Text>\n <View style={[styles.card, { backgroundColor: colors.surface }]}>\n {readings.map((r, i) => (\n <React.Fragment key={r.id}>\n {i > 0 ? <View style={[styles.rowLine, { backgroundColor: colors.border }]} /> : null}\n <View style={styles.readingRow}>\n <Text style={[styles.readingValue, { color: colors.text }]}>\n {describeReading(r, units)}\n </Text>\n <Text style={[styles.readingWhen, { color: colors.textMuted }]}>\n {whenLabel(r.at, now)}\n </Text>\n {r.kind === 'blood-pressure' && r.problems?.length ? (\n <Text style={[styles.readingNote, { color: colors.warningText }]}>\n {r.problems.join(' ')}\n </Text>\n ) : null}\n </View>\n </React.Fragment>\n ))}\n </View>\n </>\n );\n}\n\n/** Where the readings went, and how to have them saved to the health store too. */\nfunction SavedLine({ colors, onHealth }: { colors: Colors; onHealth: () => void }) {\n const health = useHealthSync();\n const [asked, setAsked] = useState<boolean | null>(null);\n useEffect(() => {\n let live = true;\n void platformWriter().then(async (w) => {\n const a = w ? await w.asked().catch(() => true) : true;\n if (live) setAsked(a);\n });\n return () => {\n live = false;\n };\n }, [health.sync.connected]);\n const allowSaving = async () => {\n const w = await platformWriter();\n if (!w) return;\n await w.requestAccess().catch(() => undefined);\n setAsked(true);\n void deviceStore.flush();\n };\n if (!health.sync.connected) {\n return (\n <Pressable\n onPress={onHealth}\n accessibilityRole=\"link\"\n style={({ pressed }) => [styles.savedLine, pressed && styles.pressed]}\n >\n <Ionicons name=\"checkmark-circle\" size={18} color={colors.successText} />\n <Text style={[styles.savedText, { color: colors.textMuted }]}>\n Saved for your coach. <Text style={{ color: colors.primary }}>Connect {STORE_NAME}</Text> to keep it\n there too.\n </Text>\n </Pressable>\n );\n }\n if (asked === false) {\n return (\n <View style={styles.savedBlock}>\n <Text style={[styles.savedText, { color: colors.textMuted }]}>Saved for your coach.</Text>\n <SecondaryButton\n label={`Also save to ${STORE_NAME}`}\n colors={colors}\n onPress={() => {\n void allowSaving();\n }}\n />\n </View>\n );\n }\n return (\n <View style={styles.savedLine}>\n <Ionicons name=\"checkmark-circle\" size={18} color={colors.successText} />\n <Text style={[styles.savedText, { color: colors.textMuted }]}>\n Saved for your coach and to {STORE_NAME}.\n </Text>\n </View>\n );\n}\n\nfunction FoundRow({\n found,\n first,\n colors,\n onPress,\n}: {\n found: FoundDevice;\n first: boolean;\n colors: Colors;\n onPress: () => void;\n}) {\n const bars = signalBars(found.rssi);\n return (\n <>\n {!first ? <View style={[styles.rowLine, { backgroundColor: colors.border }]} /> : null}\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel={`Connect ${found.name}`}\n style={({ pressed }) => [styles.deviceRow, pressed && { backgroundColor: colors.surfaceMuted }]}\n >\n {found.kind ? (\n <KindIcon kind={found.kind} colors={colors} />\n ) : (\n <Ionicons name=\"bluetooth\" size={22} color={colors.primary} />\n )}\n <Text style={[styles.deviceName, styles.deviceText, { color: colors.text }]} numberOfLines={1}>\n {found.name}\n </Text>\n <View style={styles.signal} accessibilityLabel={`Signal ${bars} of 3`}>\n {[1, 2, 3].map((b) => (\n <View\n key={b}\n style={[\n styles.signalBar,\n { height: 4 + b * 4, backgroundColor: b <= bars ? colors.primary : colors.border },\n ]}\n />\n ))}\n </View>\n </Pressable>\n </>\n );\n}\n\n// ------------------------------------------------------------------- Home\n\nfunction Home({\n colors,\n isDark,\n units,\n onAdd,\n onOpen,\n onHealth,\n}: {\n colors: Colors;\n isDark: boolean;\n units: 'metric' | 'imperial';\n onAdd: () => void;\n onOpen: (id: string) => void;\n onHealth: () => void;\n}) {\n const devices = useDevices();\n const now = Date.now();\n if (!devices.loaded) return <ActivityIndicator style={styles.loading} color={colors.primary} />;\n const latestOf = (d: PairedDevice) =>\n devices.readings\n .filter((r) => r.deviceId === d.id)\n .reduce<DeviceReading | undefined>((a, b) => (!a || b.at > a.at ? b : a), undefined);\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n {devices.devices.length ? (\n <>\n <Text style={[styles.sectionTitle, { color: colors.textMuted }]}>MY DEVICES</Text>\n <View style={[styles.card, { backgroundColor: colors.surface }]}>\n {devices.devices.map((d, i) => {\n const latest = latestOf(d);\n return (\n <React.Fragment key={d.id}>\n {i > 0 ? (\n <View style={[styles.rowLine, { backgroundColor: colors.border }]} />\n ) : null}\n <Pressable\n onPress={() => onOpen(d.id)}\n accessibilityRole=\"button\"\n accessibilityLabel={d.name}\n style={({ pressed }) => [\n styles.deviceRow,\n pressed && { backgroundColor: colors.surfaceMuted },\n ]}\n >\n <KindIcon kind={d.kind} colors={colors} />\n <View style={styles.deviceText}>\n <Text style={[styles.deviceName, { color: colors.text }]} numberOfLines={1}>\n {d.name}\n </Text>\n <Text\n style={[styles.deviceMeta, { color: colors.textMuted }]}\n numberOfLines={2}\n >\n {latest\n ? `${describeReading(latest, units)} · ${keepTogether(whenLabel(latest.at, now))}`\n : 'No readings yet'}\n </Text>\n </View>\n <Ionicons\n name=\"chevron-forward\"\n size={16}\n color={isDark ? '#64748b' : '#c4c4c4'}\n />\n </Pressable>\n </React.Fragment>\n );\n })}\n </View>\n </>\n ) : (\n <View style={styles.hero}>\n <View style={[styles.heroIcon, { backgroundColor: colors.primarySoft }]}>\n <Ionicons name=\"bluetooth\" size={30} color={colors.primary} />\n </View>\n <Text style={[styles.heroTitle, { color: colors.text }]}>Connect a device</Text>\n <Text style={[styles.heroBody, { color: colors.textMuted }]}>\n Pair a scale, blood-pressure monitor, heart-rate strap, pulse oximeter, thermometer or glucose\n meter. Each reading goes to your coach, and to {STORE_NAME} when you connected it.\n </Text>\n </View>\n )}\n {devices.lastError && devices.pendingDates.length ? (\n <Notice\n colors={colors}\n tone=\"warning\"\n icon=\"cloud-offline-outline\"\n text={`Readings are kept on this phone and sent when Yantra can reach your coach. ${devices.lastError}`}\n />\n ) : null}\n <View style={styles.actions}>\n <PrimaryButton label=\"Add a device\" onPress={onAdd} />\n </View>\n <Text style={[styles.footnote, { color: colors.textMuted }]}>\n Devices that use the Bluetooth health standards pair here. For a brand scale with its own app, such as\n RENPHO or Withings, turn on its {STORE_NAME} sync; Yantra reads it there.\n </Text>\n <Pressable\n onPress={onHealth}\n accessibilityRole=\"link\"\n style={({ pressed }) => [styles.linkRow, pressed && styles.pressed]}\n >\n <Text style={[styles.link, { color: colors.primary }]}>{STORE_NAME} settings</Text>\n <Ionicons name=\"chevron-forward\" size={14} color={colors.primary} />\n </Pressable>\n </ScrollView>\n );\n}\n\n// --------------------------------------------------------------- Pick kind\n\nfunction PickKind({\n colors,\n isDark,\n onPick,\n}: {\n colors: Colors;\n isDark: boolean;\n onPick: (kind: DeviceKindId) => void;\n}) {\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n <Text style={[styles.question, { color: colors.text }]}>Which device do you want to connect?</Text>\n <View style={styles.kindList}>\n {DEVICE_KINDS.map((k) => (\n <Pressable\n key={k.id}\n onPress={() => onPick(k.id)}\n accessibilityRole=\"button\"\n accessibilityLabel={k.title}\n style={({ pressed }) => [\n styles.kindCard,\n { backgroundColor: colors.surface },\n pressed && { backgroundColor: colors.surfaceMuted },\n ]}\n >\n <KindIcon kind={k.id} colors={colors} large />\n <View style={styles.deviceText}>\n <Text style={[styles.kindTitle, { color: colors.text }]}>{k.title}</Text>\n <Text style={[styles.deviceMeta, { color: colors.textMuted }]}>{k.subtitle}</Text>\n </View>\n <Ionicons name=\"chevron-forward\" size={16} color={isDark ? '#64748b' : '#c4c4c4'} />\n </Pressable>\n ))}\n </View>\n </ScrollView>\n );\n}\n\n// ----------------------------------------------------------------- Measure\n\nfunction LivePanel({\n kind,\n colors,\n live,\n recording,\n connected,\n onStart,\n onStop,\n onSave,\n}: {\n kind: DeviceKindId;\n colors: Colors;\n live: { bpm?: number; spo2?: number; pulse?: number };\n recording?: { startedAt: number; workoutType: string; avgHr?: number; maxHr?: number };\n connected: boolean;\n onStart: (type: string) => void;\n onStop: () => void;\n onSave: () => void;\n}) {\n const [type, setType] = useState('run');\n const [, tick] = useState(0);\n useEffect(() => {\n if (!recording) return undefined;\n const t = setInterval(() => tick((n) => n + 1), 1000);\n return () => clearInterval(t);\n }, [recording]);\n if (kind === 'heart-rate') {\n const elapsed = recording ? Math.max(0, Math.floor((Date.now() - recording.startedAt) / 1000)) : 0;\n return (\n <View style={[styles.card, styles.livePanel, { backgroundColor: colors.surface }]}>\n <Text\n style={[styles.liveValue, { color: colors.text }]}\n accessibilityLabel={`Heart rate ${live.bpm ?? 0} beats per minute`}\n >\n {live.bpm ?? '--'}\n <Text style={[styles.liveUnit, { color: colors.textMuted }]}> bpm</Text>\n </Text>\n {recording ? (\n <>\n <Text style={[styles.liveMeta, { color: colors.textMuted }]}>\n {clockOf(elapsed)} · average {recording.avgHr ?? '--'} · max {recording.maxHr ?? '--'}\n </Text>\n <PrimaryButton label=\"Stop and save\" onPress={onStop} />\n </>\n ) : null}\n {!recording && connected ? (\n <>\n <View style={styles.chips}>\n {WORKOUT_TYPES.map((w) => (\n <Pressable\n key={w.id}\n onPress={() => setType(w.id)}\n accessibilityRole=\"radio\"\n accessibilityState={{ selected: type === w.id }}\n style={[\n styles.chip,\n { borderColor: type === w.id ? colors.primary : colors.border },\n type === w.id && { backgroundColor: colors.primarySoft },\n ]}\n >\n <Text\n style={[\n styles.chipLabel,\n { color: type === w.id ? colors.primary : colors.text },\n ]}\n >\n {w.label}\n </Text>\n </Pressable>\n ))}\n </View>\n <PrimaryButton label=\"Start session\" onPress={() => onStart(type)} />\n </>\n ) : null}\n </View>\n );\n }\n return (\n <View style={[styles.card, styles.livePanel, { backgroundColor: colors.surface }]}>\n <Text style={[styles.liveValue, { color: colors.text }]}>\n {live.spo2 ?? '--'}\n <Text style={[styles.liveUnit, { color: colors.textMuted }]}>%</Text>\n </Text>\n <Text style={[styles.liveMeta, { color: colors.textMuted }]}>\n Blood oxygen{live.pulse ? ` · pulse ${live.pulse}` : ''}\n </Text>\n {connected ? <PrimaryButton label=\"Save this reading\" onPress={onSave} /> : null}\n </View>\n );\n}\n\nfunction Measure({\n kind,\n deviceId,\n colors,\n units,\n onDone,\n onHealth,\n}: {\n kind: DeviceKindId;\n deviceId?: string;\n colors: Colors;\n units: 'metric' | 'imperial';\n onDone: () => void;\n onHealth: () => void;\n}) {\n const { snapshot, session } = useDeviceSession(kind, deviceId);\n const { state, readings, live, recording, notices } = snapshot;\n const info = deviceKind(kind);\n const now = Date.now();\n const retry = () => {\n void session?.start();\n };\n\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n {state.step === 'starting' ? <ActivityIndicator style={styles.loading} color={colors.primary} /> : null}\n\n {state.step === 'unavailable' ? (\n <Notice colors={colors} tone=\"warning\" icon=\"information-circle\" text={state.reason} />\n ) : null}\n\n {state.step === 'radio' ? (\n <View style={styles.center}>\n <BluetoothPulse colors={colors} active={false} />\n <Text style={[styles.statusTitle, { color: colors.text }]}>{radioCopy(state.radio).title}</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>{radioCopy(state.radio).body}</Text>\n {state.radio === 'unauthorized' ? (\n <PrimaryButton\n label=\"Open Settings\"\n onPress={() => {\n void Linking.openSettings();\n }}\n />\n ) : null}\n {state.radio === 'off' ? <PrimaryButton label=\"Try again\" onPress={retry} /> : null}\n </View>\n ) : null}\n\n {state.step === 'scanning' ? (\n <>\n <BluetoothPulse colors={colors} active />\n <Text style={[styles.statusTitle, { color: colors.text }]}>\n {deviceId ? 'Looking for your device' : 'Looking for devices nearby'}\n </Text>\n <View style={[styles.card, styles.guidance, { backgroundColor: colors.surface }]}>\n {info.steps.map((line, i) => (\n <View key={line} style={styles.guidanceRow}>\n <View style={[styles.stepDot, { backgroundColor: colors.primarySoft }]}>\n <Text style={[styles.stepNumber, { color: colors.primary }]}>{i + 1}</Text>\n </View>\n <Text style={[styles.guidanceText, { color: colors.text }]}>{line}</Text>\n </View>\n ))}\n </View>\n {state.hint ? (\n <Notice\n colors={colors}\n tone=\"warning\"\n icon=\"information-circle\"\n text={`Nothing yet. ${state.hint} Keep it close to the phone.`}\n />\n ) : null}\n {state.found.length ? (\n <>\n <Text style={[styles.sectionTitle, { color: colors.textMuted }]}>NEARBY</Text>\n <View style={[styles.card, { backgroundColor: colors.surface }]}>\n {state.found.map((f, i) => (\n <FoundRow\n key={f.id}\n found={f}\n first={i === 0}\n colors={colors}\n onPress={() => {\n void session?.pick(f);\n }}\n />\n ))}\n </View>\n </>\n ) : null}\n </>\n ) : null}\n\n {state.step === 'connecting' ? (\n <View style={styles.center}>\n <ActivityIndicator color={colors.primary} size=\"large\" />\n <Text style={[styles.statusTitle, { color: colors.text }]}>Connecting to {state.device.name}</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>\n If your phone asks to pair, tap Pair.\n </Text>\n </View>\n ) : null}\n\n {state.step === 'connected' && !readings.length && !live ? (\n <View style={styles.center}>\n <BluetoothPulse colors={colors} active connected />\n <Text style={[styles.statusTitle, { color: colors.text }]}>{info.waitingFor}</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>\n Connected to {state.device.name}.\n </Text>\n </View>\n ) : null}\n\n {(state.step === 'connected' || state.step === 'ended') && live ? (\n <LivePanel\n kind={kind}\n colors={colors}\n live={live}\n recording={recording}\n connected={state.step === 'connected'}\n onStart={(type) => session?.startRecording(type)}\n onStop={() => {\n void session?.stopRecording();\n }}\n onSave={() => {\n void session?.saveLive();\n }}\n />\n ) : null}\n\n {notices.map((n) => (\n <Notice key={n} colors={colors} tone=\"warning\" icon=\"information-circle\" text={n} />\n ))}\n\n {readings.length ? (\n <ReadingsCard title=\"JUST MEASURED\" readings={readings} colors={colors} units={units} now={now} />\n ) : null}\n {readings.length ? <SavedLine colors={colors} onHealth={onHealth} /> : null}\n\n {state.step === 'ended' ? (\n <View style={styles.actions}>\n {!readings.length ? (\n <Text style={[styles.actionHint, { color: colors.textMuted }]}>\n The device went to sleep before it sent a measurement.\n </Text>\n ) : null}\n <PrimaryButton label=\"Done\" onPress={onDone} />\n <SecondaryButton label=\"Measure again\" colors={colors} onPress={() => session?.scan()} />\n </View>\n ) : null}\n\n {state.step === 'connected' && readings.length ? (\n <View style={styles.actions}>\n <PrimaryButton label=\"Done\" onPress={onDone} />\n </View>\n ) : null}\n\n {state.step === 'error' ? (\n <View style={styles.center}>\n <Ionicons name=\"alert-circle\" size={40} color={colors.dangerText} />\n <Text style={[styles.statusTitle, { color: colors.text }]}>{state.message}</Text>\n <PrimaryButton label=\"Try again\" onPress={retry} />\n </View>\n ) : null}\n </ScrollView>\n );\n}\n\n// ------------------------------------------------------------ Device detail\n\nfunction DeviceDetail({\n id,\n colors,\n units,\n onMeasure,\n onForgot,\n}: {\n id: string;\n colors: Colors;\n units: 'metric' | 'imperial';\n onMeasure: (kind: DeviceKindId) => void;\n onForgot: () => void;\n}) {\n const devices = useDevices();\n const device = devices.devices.find((d) => d.id === id);\n const readings = useMemo(\n () =>\n devices.readings\n .filter((r) => r.deviceId === id)\n .sort((a, b) => b.at - a.at)\n .slice(0, 20),\n [devices.readings, id],\n );\n if (!device) return null;\n const forget = () =>\n Alert.alert(`Forget ${device.name}?`, 'Its readings stay in Yantra. To use it again, pair it again.', [\n { text: 'Cancel', style: 'cancel' },\n {\n text: 'Forget',\n style: 'destructive',\n onPress: () => {\n void deviceStore.forget(id).then(onForgot);\n },\n },\n ]);\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n <View style={styles.hero}>\n <KindIcon kind={device.kind} colors={colors} large />\n <Text style={[styles.heroTitle, { color: colors.text }]}>{device.name}</Text>\n <Text style={[styles.heroBody, { color: colors.textMuted }]}>\n {deviceKind(device.kind).title}\n {device.scaleUser ? ` · user ${device.scaleUser.userIndex} on this scale` : ''}\n </Text>\n </View>\n <View style={styles.actions}>\n <PrimaryButton\n label={device.kind === 'heart-rate' ? 'Start a session' : 'Take a reading'}\n onPress={() => onMeasure(device.kind)}\n />\n </View>\n {readings.length ? (\n <ReadingsCard title=\"READINGS\" readings={readings} colors={colors} units={units} now={Date.now()} />\n ) : (\n <Text style={[styles.footnote, { color: colors.textMuted }]}>No readings from this device yet.</Text>\n )}\n <View style={[styles.card, styles.secondaryCard, { backgroundColor: colors.surface }]}>\n <Pressable\n onPress={forget}\n accessibilityRole=\"button\"\n style={({ pressed }) => [styles.row, pressed && { backgroundColor: colors.surfaceMuted }]}\n >\n <Text style={[styles.rowLabelWide, { color: colors.dangerText }]}>Forget this device</Text>\n </Pressable>\n </View>\n </ScrollView>\n );\n}\n\nexport default function DevicesScreen() {\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n const route = useRoute<RouteProp<Record<string, DevicesParams>, string>>();\n const { isDark } = useAppTheme();\n const colors = mobileColors(isDark);\n const insets = useSafeAreaInsets();\n const devices = useDevices();\n const [stack, setStack] = useState<Step[]>(() =>\n route?.params?.add ? [{ name: 'home' }, { name: 'pick' }] : [{ name: 'home' }],\n );\n const step = stack[stack.length - 1];\n const units = devices.person?.units ?? 'metric';\n\n const orgName = useMemo(() => {\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params?.orgName]);\n\n const push = useCallback((next: Step) => setStack((s) => [...s, next]), []);\n const pop = useCallback(() => {\n if (stack.length > 1) {\n setStack((s) => s.slice(0, -1));\n return true;\n }\n if (navigation?.canGoBack?.()) {\n navigation.goBack();\n return true;\n }\n navigation?.dispatch?.(\n CommonActions.navigate({ name: 'MainStack.Account', params: orgName ? { orgName } : undefined }),\n );\n return true;\n }, [stack.length, navigation, orgName]);\n\n useEffect(() => {\n const sub = BackHandler.addEventListener('hardwareBackPress', pop);\n return () => sub.remove();\n }, [pop]);\n\n const openHealth = useCallback(() => {\n navigation?.navigate?.('MainStack.Health', orgName ? { orgName } : undefined);\n }, [navigation, orgName]);\n\n const title = stepTitle(step, devices.devices);\n\n return (\n <SafeAreaView edges={['top', 'left', 'right']} style={[styles.safe, { backgroundColor: colors.bg }]}>\n <View style={[styles.header, { paddingTop: insets.top > 0 ? 4 : 10 }]}>\n <Pressable\n onPress={pop}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Go back\"\n style={({ pressed }) => [\n styles.backCircle,\n { backgroundColor: colors.surface },\n pressed && styles.pressed,\n ]}\n >\n <Ionicons name=\"chevron-back\" size={22} color={colors.text} />\n </Pressable>\n <Text style={[styles.headerTitle, { color: colors.text }]} numberOfLines={1}>\n {title}\n </Text>\n <View style={styles.headerSpacer} />\n </View>\n {step.name === 'home' ? (\n <Home\n colors={colors}\n isDark={isDark}\n units={units}\n onAdd={() => push({ name: 'pick' })}\n onOpen={(id) => push({ name: 'device', id })}\n onHealth={openHealth}\n />\n ) : null}\n {step.name === 'pick' ? (\n <PickKind colors={colors} isDark={isDark} onPick={(kind) => push({ name: 'measure', kind })} />\n ) : null}\n {step.name === 'measure' ? (\n <Measure\n key={`${step.kind}:${step.deviceId ?? ''}`}\n kind={step.kind}\n deviceId={step.deviceId}\n colors={colors}\n units={units}\n onDone={() => setStack([{ name: 'home' }])}\n onHealth={openHealth}\n />\n ) : null}\n {step.name === 'device' ? (\n <DeviceDetail\n id={step.id}\n colors={colors}\n units={units}\n onMeasure={(kind) => push({ name: 'measure', kind, deviceId: step.id })}\n onForgot={() => setStack([{ name: 'home' }])}\n />\n ) : null}\n </SafeAreaView>\n );\n}\n"],"names":["React","_a","_b"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/screens/Devices/index.tsx"],"sourcesContent":["/**\n * Devices: the Bluetooth health devices the person paired, and pairing a new\n * one. One route with its own small stack (home -> pick a kind -> measure, or\n * home -> a device -> measure), so the flow never leaves the screen:\n *\n * - home: the paired devices with their last reading, and \"Add a device\";\n * - pick: which kind of device (scale, blood pressure, heart rate ...);\n * - measure: how to wake it, the devices found nearby, connecting, waiting for\n * a measurement (or live heart rate / oxygen), and what it measured;\n * - device: its readings, take another, forget it.\n *\n * Only devices that speak the Bluetooth SIG health profiles pair here. A brand\n * scale with its own app (RENPHO, Withings ...) keeps that app; it writes to\n * Apple Health / Health Connect and Yantra reads it there, which the home says.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n ActivityIndicator,\n Alert,\n Animated,\n BackHandler,\n Easing,\n Linking,\n Platform,\n Pressable,\n ScrollView,\n StyleSheet,\n View,\n} from 'react-native';\nimport { Ionicons } from '@expo/vector-icons';\nimport { Text } from '@admin-layout/gluestack-ui-mobile';\nimport {\n CommonActions,\n useNavigation,\n useRoute,\n type NavigationProp,\n type ParamListBase,\n type RouteProp,\n} from '@react-navigation/native';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { mobileColors, mobileTokens } from '../../theme/mobileTokens';\nimport { useAppTheme } from '../../theme/AppThemeProvider';\nimport { DEVICE_KINDS, deviceKind, type DeviceKindId } from '../../features/devices/catalog';\nimport { deviceStore, platformWriter, useDeviceSession, useDevices } from '../../features/devices/devices';\nimport { describeReading, type DeviceReading } from '../../features/devices/readings';\nimport { compositionRows } from '../../features/devices/bodyComposition';\nimport type { PairedDevice } from '../../features/devices/deviceStore';\nimport type { FoundDevice, RadioState } from '../../features/devices/link';\nimport type { LiveValue } from '../../features/devices/drivers';\nimport { useHealthSync } from '../../features/health/healthSync';\n\ntype Colors = ReturnType<typeof mobileColors>;\ntype Glyph = keyof typeof Ionicons.glyphMap;\n/** `add`: open straight on \"Which device\" (the Fitness page's Add a device). */\ntype DevicesParams = { orgName?: string; add?: boolean } | undefined;\ntype Step =\n | { name: 'home' }\n | { name: 'pick' }\n | { name: 'measure'; kind: DeviceKindId; deviceId?: string }\n | { name: 'device'; id: string };\n\nconst IS_IOS = Platform.OS === 'ios';\n/** The app's surfaces are white on a white page in light mode; an edge keeps each card readable as one. */\nconst CARD_EDGE = 'rgba(148,163,184,0.3)';\nconst STORE_NAME = IS_IOS ? 'Apple Health' : 'Health Connect';\nconst WORKOUT_TYPES: Array<{ id: string; label: string }> = [\n { id: 'run', label: 'Run' },\n { id: 'walk', label: 'Walk' },\n { id: 'cycle', label: 'Ride' },\n { id: 'strength', label: 'Strength' },\n { id: 'hiit', label: 'HIIT' },\n { id: 'other', label: 'Other' },\n];\n\nconst styles = StyleSheet.create({\n safe: { flex: 1 },\n header: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingBottom: 8, minHeight: 52 },\n backCircle: {\n width: 40,\n height: 40,\n borderRadius: 20,\n alignItems: 'center',\n justifyContent: 'center',\n ...mobileTokens.shadow.card,\n },\n headerTitle: { flex: 1, textAlign: 'center', fontSize: 17, fontWeight: '600', marginHorizontal: 8 },\n headerSpacer: { width: 40, height: 40 },\n pressed: { opacity: 0.72 },\n loading: { marginTop: 48 },\n scroll: { paddingHorizontal: 16, paddingBottom: 40 },\n hero: { alignItems: 'center', paddingTop: 8, paddingBottom: 16, gap: 10 },\n heroIcon: { width: 64, height: 64, borderRadius: 32, alignItems: 'center', justifyContent: 'center' },\n heroTitle: { fontSize: 20, fontWeight: '700', textAlign: 'center' },\n heroBody: { fontSize: 15, lineHeight: 21, textAlign: 'center', paddingHorizontal: 8 },\n card: { borderRadius: 16, overflow: 'hidden', borderWidth: 1, borderColor: CARD_EDGE },\n secondaryCard: { marginTop: 20 },\n sectionTitle: {\n fontSize: 13,\n fontWeight: '600',\n letterSpacing: 0.4,\n marginTop: 24,\n marginBottom: 8,\n marginLeft: 16,\n },\n row: { flexDirection: 'row', alignItems: 'center', minHeight: 52, paddingHorizontal: 16, gap: 12 },\n rowLabelWide: { flex: 1, fontSize: 16 },\n rowLine: { height: StyleSheet.hairlineWidth, marginLeft: 16 },\n deviceRow: { flexDirection: 'row', alignItems: 'center', minHeight: 64, paddingHorizontal: 16, gap: 12 },\n deviceText: { flex: 1, minWidth: 0 },\n deviceName: { fontSize: 16, fontWeight: '600' },\n deviceMeta: { fontSize: 14, marginTop: 2 },\n kindIcon: { alignItems: 'center', justifyContent: 'center' },\n question: { fontSize: 22, fontWeight: '700', textAlign: 'center', marginTop: 8, marginBottom: 20, lineHeight: 28 },\n kindList: { gap: 10 },\n kindCard: {\n flexDirection: 'row',\n alignItems: 'center',\n borderRadius: 16,\n padding: 14,\n gap: 14,\n borderWidth: 1,\n borderColor: CARD_EDGE,\n },\n kindTitle: { fontSize: 16, fontWeight: '600' },\n center: { alignItems: 'center', paddingTop: 24, gap: 12 },\n statusTitle: { fontSize: 19, fontWeight: '700', textAlign: 'center', marginTop: 4 },\n statusBody: { fontSize: 15, lineHeight: 21, textAlign: 'center', paddingHorizontal: 8 },\n guidance: { marginTop: 16, paddingVertical: 8 },\n guidanceRow: { flexDirection: 'row', alignItems: 'flex-start', paddingHorizontal: 16, paddingVertical: 8, gap: 12 },\n stepDot: { width: 24, height: 24, borderRadius: 12, alignItems: 'center', justifyContent: 'center', marginTop: 1 },\n stepNumber: { fontSize: 13, fontWeight: '700' },\n guidanceText: { flex: 1, fontSize: 15, lineHeight: 22 },\n pulseBox: {\n alignSelf: 'center',\n width: 120,\n height: 120,\n alignItems: 'center',\n justifyContent: 'center',\n marginTop: 16,\n },\n pulseRing: { position: 'absolute', width: 64, height: 64, borderRadius: 32 },\n pulseCore: { width: 64, height: 64, borderRadius: 32, alignItems: 'center', justifyContent: 'center' },\n signal: { flexDirection: 'row', alignItems: 'flex-end', gap: 2, height: 16 },\n signalBar: { width: 4, borderRadius: 1 },\n livePanel: { alignItems: 'center', padding: 20, marginTop: 16, gap: 12 },\n liveValue: { fontSize: 56, fontWeight: '700', fontVariant: ['tabular-nums'] },\n liveUnit: { fontSize: 18, fontWeight: '500' },\n liveMeta: { fontSize: 15, fontVariant: ['tabular-nums'] },\n chips: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'center', gap: 8 },\n chip: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 14, paddingVertical: 8 },\n chipLabel: { fontSize: 14, fontWeight: '600' },\n readingRow: { paddingHorizontal: 16, paddingVertical: 12, gap: 2 },\n readingValue: { fontSize: 16, fontWeight: '600' },\n readingWhen: { fontSize: 14 },\n readingNote: { fontSize: 14, marginTop: 2 },\n measureBox: { alignItems: 'center', paddingVertical: 24, gap: 6 },\n measureRing: { position: 'absolute', top: 24, width: 176, height: 176, borderRadius: 88, borderWidth: 2 },\n measureCore: {\n width: 176,\n height: 176,\n borderRadius: 88,\n alignItems: 'center',\n justifyContent: 'center',\n marginBottom: 12,\n },\n measureWeight: { fontSize: 44, fontWeight: '700' },\n measureUnit: { fontSize: 18, fontWeight: '600' },\n compositionGrid: { flexDirection: 'row', flexWrap: 'wrap', marginTop: 10, rowGap: 10 },\n compositionItem: { width: '33.33%', paddingRight: 8 },\n compositionLabel: { fontSize: 12 },\n compositionValue: { fontSize: 15, fontWeight: '600', marginTop: 1 },\n savedLine: { flexDirection: 'row', alignItems: 'center', gap: 8, marginTop: 12, marginHorizontal: 4 },\n savedBlock: { marginTop: 12, gap: 10 },\n savedText: { flex: 1, fontSize: 14, lineHeight: 20 },\n notice: { flexDirection: 'row', borderRadius: 14, padding: 12, marginTop: 12, gap: 8 },\n noticeIcon: { marginTop: 1 },\n noticeText: { flex: 1, fontSize: 14, lineHeight: 20 },\n actions: { marginTop: 20, gap: 10, alignItems: 'stretch' },\n actionHint: { fontSize: 15, lineHeight: 21, textAlign: 'center' },\n primary: {\n backgroundColor: mobileTokens.color.primary,\n borderRadius: 14,\n minHeight: 50,\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 18,\n alignSelf: 'stretch',\n },\n primaryLabel: { color: '#fff', fontSize: 16, fontWeight: '600' },\n secondary: {\n borderRadius: 14,\n minHeight: 48,\n alignItems: 'center',\n justifyContent: 'center',\n borderWidth: 1,\n paddingHorizontal: 18,\n },\n secondaryLabel: { fontSize: 16, fontWeight: '600' },\n footnote: { fontSize: 13, lineHeight: 18, marginTop: 16, marginHorizontal: 16 },\n linkRow: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n marginTop: 10,\n marginHorizontal: 16,\n alignSelf: 'flex-start',\n },\n link: { fontSize: 14, fontWeight: '600' },\n});\n\nfunction stepTitle(step: Step, paired: PairedDevice[]): string {\n switch (step.name) {\n case 'pick':\n return 'Add a device';\n case 'measure':\n return deviceKind(step.kind).title;\n case 'device':\n return paired.find((d) => d.id === step.id)?.name ?? 'Device';\n default:\n return 'Devices';\n }\n}\n\n/** What to say when the radio is not ready to scan. */\nfunction radioCopy(radio: RadioState): { title: string; body: string } {\n if (radio === 'off') return { title: 'Turn on Bluetooth', body: 'Yantra finds your device over Bluetooth.' };\n if (radio === 'unauthorized') {\n return {\n title: 'Allow Bluetooth for Yantra',\n body: 'Yantra needs Bluetooth to find and read your device. Turn it on for Yantra in Settings.',\n };\n }\n return { title: 'This phone has no Bluetooth Yantra can use', body: '' };\n}\n\n/** Bars for the signal strength of a device found nearby. */\nfunction signalBars(rssi: number | undefined): number {\n if (rssi === undefined) return 1;\n if (rssi > -60) return 3;\n if (rssi > -80) return 2;\n return 1;\n}\n\nfunction whenLabel(at: number, now: number): string {\n const d = new Date(at);\n const time = d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });\n const startOf = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const days = Math.round((startOf(new Date(now)) - startOf(d)) / 86_400_000);\n if (days === 0) return `Today, ${time}`;\n if (days === 1) return `Yesterday, ${time}`;\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n}\n\n/** \"Today, 7:31 AM\" wraps as one piece, never with \"AM\" alone on the next line. */\nfunction keepTogether(text: string): string {\n return text.replace(/\\s/g, '\\u00a0');\n}\n\nfunction clockOf(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${String(s).padStart(2, '0')}`;\n}\n\n// ------------------------------------------------------------------ Pieces\n\nfunction KindIcon({ kind, colors, large }: { kind: DeviceKindId; colors: Colors; large?: boolean }) {\n const size = large ? 48 : 36;\n return (\n <View\n style={[\n styles.kindIcon,\n { width: size, height: size, borderRadius: size / 2, backgroundColor: colors.primarySoft },\n ]}\n >\n <Ionicons name={deviceKind(kind).icon as Glyph} size={large ? 24 : 18} color={colors.primary} />\n </View>\n );\n}\n\n/** The Bluetooth mark with a ring that breathes while scanning. */\nfunction BluetoothPulse({ colors, active, connected }: { colors: Colors; active: boolean; connected?: boolean }) {\n const pulse = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n if (!active) return undefined;\n const loop = Animated.loop(\n Animated.timing(pulse, {\n toValue: 1,\n duration: 1600,\n easing: Easing.out(Easing.ease),\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [active, pulse]);\n const scale = pulse.interpolate({ inputRange: [0, 1], outputRange: [1, 1.9] });\n const opacity = pulse.interpolate({ inputRange: [0, 1], outputRange: [0.45, 0] });\n return (\n <View style={styles.pulseBox} accessibilityElementsHidden importantForAccessibility=\"no-hide-descendants\">\n {active ? (\n <Animated.View\n style={[styles.pulseRing, { backgroundColor: colors.primary, opacity, transform: [{ scale }] }]}\n />\n ) : null}\n <View style={[styles.pulseCore, { backgroundColor: connected ? colors.successText : colors.primary }]}>\n <Ionicons name={connected ? 'checkmark' : 'bluetooth'} size={28} color=\"#fff\" />\n </View>\n </View>\n );\n}\n\nfunction Notice({\n colors,\n tone,\n icon,\n text,\n}: {\n colors: Colors;\n tone: 'warning' | 'danger';\n icon: Glyph;\n text: string;\n}) {\n const bg = tone === 'danger' ? colors.dangerSoft : colors.warningSoft;\n const fg = tone === 'danger' ? colors.dangerText : colors.warningText;\n return (\n <View style={[styles.notice, { backgroundColor: bg }]} accessibilityRole=\"alert\">\n <Ionicons name={icon} size={18} color={fg} style={styles.noticeIcon} />\n <Text style={[styles.noticeText, { color: fg }]}>{text}</Text>\n </View>\n );\n}\n\nfunction PrimaryButton({ label, onPress }: { label: string; onPress: () => void }) {\n return (\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n style={({ pressed }) => [styles.primary, pressed && styles.pressed]}\n >\n <Text style={styles.primaryLabel}>{label}</Text>\n </Pressable>\n );\n}\n\nfunction SecondaryButton({ label, onPress, colors }: { label: string; onPress: () => void; colors: Colors }) {\n return (\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n style={({ pressed }) => [\n styles.secondary,\n { borderColor: colors.border, backgroundColor: colors.surface },\n pressed && styles.pressed,\n ]}\n >\n <Text style={[styles.secondaryLabel, { color: colors.text }]}>{label}</Text>\n </Pressable>\n );\n}\n\nfunction ReadingsCard({\n title,\n readings,\n colors,\n units,\n now,\n}: {\n title: string;\n readings: DeviceReading[];\n colors: Colors;\n units: 'metric' | 'imperial';\n now: number;\n}) {\n return (\n <>\n <Text style={[styles.sectionTitle, { color: colors.textMuted }]}>{title}</Text>\n <View style={[styles.card, { backgroundColor: colors.surface }]}>\n {readings.map((r, i) => (\n <React.Fragment key={r.id}>\n {i > 0 ? <View style={[styles.rowLine, { backgroundColor: colors.border }]} /> : null}\n <View style={styles.readingRow}>\n <Text style={[styles.readingValue, { color: colors.text }]}>\n {describeReading(r, units)}\n </Text>\n <Text style={[styles.readingWhen, { color: colors.textMuted }]}>\n {whenLabel(r.at, now)}\n </Text>\n {r.kind === 'blood-pressure' && r.problems?.length ? (\n <Text style={[styles.readingNote, { color: colors.warningText }]}>\n {r.problems.join(' ')}\n </Text>\n ) : null}\n {r.kind === 'body' && r.composition ? (\n <View style={styles.compositionGrid}>\n {compositionRows(r.composition, units).map((m) => (\n <View key={m.label} style={styles.compositionItem}>\n <Text style={[styles.compositionLabel, { color: colors.textMuted }]}>\n {m.label}\n </Text>\n <Text style={[styles.compositionValue, { color: colors.text }]}>\n {m.value}\n </Text>\n </View>\n ))}\n </View>\n ) : null}\n </View>\n </React.Fragment>\n ))}\n </View>\n </>\n );\n}\n\n/** Where the readings went, and how to have them saved to the health store too. */\nfunction SavedLine({ colors, onHealth }: { colors: Colors; onHealth: () => void }) {\n const health = useHealthSync();\n const [asked, setAsked] = useState<boolean | null>(null);\n useEffect(() => {\n let live = true;\n void platformWriter().then(async (w) => {\n const a = w ? await w.asked().catch(() => true) : true;\n if (live) setAsked(a);\n });\n return () => {\n live = false;\n };\n }, [health.sync.connected]);\n const allowSaving = async () => {\n const w = await platformWriter();\n if (!w) return;\n await w.requestAccess().catch(() => undefined);\n setAsked(true);\n void deviceStore.flush();\n };\n if (!health.sync.connected) {\n return (\n <Pressable\n onPress={onHealth}\n accessibilityRole=\"link\"\n style={({ pressed }) => [styles.savedLine, pressed && styles.pressed]}\n >\n <Ionicons name=\"checkmark-circle\" size={18} color={colors.successText} />\n <Text style={[styles.savedText, { color: colors.textMuted }]}>\n Saved for your coach. <Text style={{ color: colors.primary }}>Connect {STORE_NAME}</Text> to keep it\n there too.\n </Text>\n </Pressable>\n );\n }\n if (asked === false) {\n return (\n <View style={styles.savedBlock}>\n <Text style={[styles.savedText, { color: colors.textMuted }]}>Saved for your coach.</Text>\n <SecondaryButton\n label={`Also save to ${STORE_NAME}`}\n colors={colors}\n onPress={() => {\n void allowSaving();\n }}\n />\n </View>\n );\n }\n return (\n <View style={styles.savedLine}>\n <Ionicons name=\"checkmark-circle\" size={18} color={colors.successText} />\n <Text style={[styles.savedText, { color: colors.textMuted }]}>\n Saved for your coach and to {STORE_NAME}.\n </Text>\n </View>\n );\n}\n\nfunction FoundRow({\n found,\n first,\n colors,\n onPress,\n}: {\n found: FoundDevice;\n first: boolean;\n colors: Colors;\n onPress: () => void;\n}) {\n const bars = signalBars(found.rssi);\n return (\n <>\n {!first ? <View style={[styles.rowLine, { backgroundColor: colors.border }]} /> : null}\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel={`Connect ${found.name}`}\n style={({ pressed }) => [styles.deviceRow, pressed && { backgroundColor: colors.surfaceMuted }]}\n >\n {found.kind ? (\n <KindIcon kind={found.kind} colors={colors} />\n ) : (\n <Ionicons name=\"bluetooth\" size={22} color={colors.primary} />\n )}\n <Text style={[styles.deviceName, styles.deviceText, { color: colors.text }]} numberOfLines={1}>\n {found.name}\n </Text>\n <View style={styles.signal} accessibilityLabel={`Signal ${bars} of 3`}>\n {[1, 2, 3].map((b) => (\n <View\n key={b}\n style={[\n styles.signalBar,\n { height: 4 + b * 4, backgroundColor: b <= bars ? colors.primary : colors.border },\n ]}\n />\n ))}\n </View>\n </Pressable>\n </>\n );\n}\n\n// ------------------------------------------------------------------- Home\n\nfunction Home({\n colors,\n isDark,\n units,\n onAdd,\n onOpen,\n onHealth,\n}: {\n colors: Colors;\n isDark: boolean;\n units: 'metric' | 'imperial';\n onAdd: () => void;\n onOpen: (id: string) => void;\n onHealth: () => void;\n}) {\n const devices = useDevices();\n const now = Date.now();\n if (!devices.loaded) return <ActivityIndicator style={styles.loading} color={colors.primary} />;\n const latestOf = (d: PairedDevice) =>\n devices.readings\n .filter((r) => r.deviceId === d.id)\n .reduce<DeviceReading | undefined>((a, b) => (!a || b.at > a.at ? b : a), undefined);\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n {devices.devices.length ? (\n <>\n <Text style={[styles.sectionTitle, { color: colors.textMuted }]}>MY DEVICES</Text>\n <View style={[styles.card, { backgroundColor: colors.surface }]}>\n {devices.devices.map((d, i) => {\n const latest = latestOf(d);\n return (\n <React.Fragment key={d.id}>\n {i > 0 ? (\n <View style={[styles.rowLine, { backgroundColor: colors.border }]} />\n ) : null}\n <Pressable\n onPress={() => onOpen(d.id)}\n accessibilityRole=\"button\"\n accessibilityLabel={d.name}\n style={({ pressed }) => [\n styles.deviceRow,\n pressed && { backgroundColor: colors.surfaceMuted },\n ]}\n >\n <KindIcon kind={d.kind} colors={colors} />\n <View style={styles.deviceText}>\n <Text style={[styles.deviceName, { color: colors.text }]} numberOfLines={1}>\n {d.name}\n </Text>\n <Text\n style={[styles.deviceMeta, { color: colors.textMuted }]}\n numberOfLines={2}\n >\n {latest\n ? `${describeReading(latest, units)} · ${keepTogether(whenLabel(latest.at, now))}`\n : 'No readings yet'}\n </Text>\n </View>\n <Ionicons\n name=\"chevron-forward\"\n size={16}\n color={isDark ? '#64748b' : '#c4c4c4'}\n />\n </Pressable>\n </React.Fragment>\n );\n })}\n </View>\n </>\n ) : (\n <View style={styles.hero}>\n <View style={[styles.heroIcon, { backgroundColor: colors.primarySoft }]}>\n <Ionicons name=\"bluetooth\" size={30} color={colors.primary} />\n </View>\n <Text style={[styles.heroTitle, { color: colors.text }]}>Connect a device</Text>\n <Text style={[styles.heroBody, { color: colors.textMuted }]}>\n Pair a scale, blood-pressure monitor, heart-rate strap, pulse oximeter, thermometer or glucose\n meter. Each reading goes to your coach, and to {STORE_NAME} when you connected it.\n </Text>\n </View>\n )}\n {devices.lastError && devices.pendingDates.length ? (\n <Notice\n colors={colors}\n tone=\"warning\"\n icon=\"cloud-offline-outline\"\n text={`Readings are kept on this phone and sent when Yantra can reach your coach. ${devices.lastError}`}\n />\n ) : null}\n <View style={styles.actions}>\n <PrimaryButton label=\"Add a device\" onPress={onAdd} />\n </View>\n <Text style={[styles.footnote, { color: colors.textMuted }]}>\n Devices that use the Bluetooth health standards pair here. For a brand scale with its own app, such as\n RENPHO or Withings, turn on its {STORE_NAME} sync; Yantra reads it there.\n </Text>\n <Pressable\n onPress={onHealth}\n accessibilityRole=\"link\"\n style={({ pressed }) => [styles.linkRow, pressed && styles.pressed]}\n >\n <Text style={[styles.link, { color: colors.primary }]}>{STORE_NAME} settings</Text>\n <Ionicons name=\"chevron-forward\" size={14} color={colors.primary} />\n </Pressable>\n </ScrollView>\n );\n}\n\n// --------------------------------------------------------------- Pick kind\n\nfunction PickKind({\n colors,\n isDark,\n onPick,\n}: {\n colors: Colors;\n isDark: boolean;\n onPick: (kind: DeviceKindId) => void;\n}) {\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n <Text style={[styles.question, { color: colors.text }]}>Which device do you want to connect?</Text>\n <View style={styles.kindList}>\n {DEVICE_KINDS.map((k) => (\n <Pressable\n key={k.id}\n onPress={() => onPick(k.id)}\n accessibilityRole=\"button\"\n accessibilityLabel={k.title}\n style={({ pressed }) => [\n styles.kindCard,\n { backgroundColor: colors.surface },\n pressed && { backgroundColor: colors.surfaceMuted },\n ]}\n >\n <KindIcon kind={k.id} colors={colors} large />\n <View style={styles.deviceText}>\n <Text style={[styles.kindTitle, { color: colors.text }]}>{k.title}</Text>\n <Text style={[styles.deviceMeta, { color: colors.textMuted }]}>{k.subtitle}</Text>\n </View>\n <Ionicons name=\"chevron-forward\" size={16} color={isDark ? '#64748b' : '#c4c4c4'} />\n </Pressable>\n ))}\n </View>\n </ScrollView>\n );\n}\n\n// ----------------------------------------------------------------- Measure\n\n/** kg to the person's units, as a string with one decimal. */\nfunction formatWeight(kg: number | undefined, units: 'metric' | 'imperial'): string {\n if (kg === undefined) return '--';\n const v = units === 'imperial' ? kg / 0.45359237 : kg;\n return (Math.round(v * 10) / 10).toFixed(1);\n}\n\n/**\n * The scale's live weighing: the number rises as the person settles onto the\n * scale, inside a soft pulsing ring. An original Yantra design, not a copy of\n * any scale maker's screen.\n */\nfunction ScaleMeasuring({ colors, live, units }: { colors: Colors; live: LiveValue; units: 'metric' | 'imperial' }) {\n const pulse = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n const loop = Animated.loop(\n Animated.timing(pulse, {\n toValue: 1,\n duration: 1400,\n easing: Easing.out(Easing.ease),\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [pulse]);\n const ringScale = pulse.interpolate({ inputRange: [0, 1], outputRange: [0.9, 1.5] });\n const ringOpacity = pulse.interpolate({ inputRange: [0, 1], outputRange: [0.5, 0] });\n const unitLabel = units === 'imperial' ? 'lb' : 'kg';\n return (\n <View style={styles.measureBox}>\n <Animated.View\n style={[\n styles.measureRing,\n { borderColor: colors.primary, opacity: ringOpacity, transform: [{ scale: ringScale }] },\n ]}\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n />\n <View style={[styles.measureCore, { backgroundColor: colors.primarySoft }]}>\n <Text style={[styles.measureWeight, { color: colors.text }]} accessibilityLabel={`${formatWeight(live.weightKg, units)} ${unitLabel}`}>\n {formatWeight(live.weightKg, units)}\n <Text style={[styles.measureUnit, { color: colors.textMuted }]}> {unitLabel}</Text>\n </Text>\n </View>\n <Text style={[styles.statusTitle, { color: colors.text }]}>Measuring</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>\n Stand still, barefoot, until it settles.\n </Text>\n </View>\n );\n}\n\n/** A plain live readout for the other brand devices (kitchen scale, tape, rope, treadmill, ring). */\nfunction BrandLive({\n kind,\n colors,\n live,\n units,\n}: {\n kind: DeviceKindId;\n colors: Colors;\n live: LiveValue;\n units: 'metric' | 'imperial';\n}) {\n const items: Array<{ label: string; value: string }> = [];\n const round1 = (n: number) => Math.round(n * 10) / 10;\n if (kind === 'kitchen-scale') items.push({ label: 'Weight', value: `${Math.round(live.grams ?? 0)} g` });\n if (kind === 'tape') {\n const cm = live.lengthCm ?? 0;\n items.push({\n label: live.bodyPart ? live.bodyPart.replace(/_/g, ' ') : 'Length',\n value: units === 'imperial' ? `${round1(cm / 2.54)} in` : `${round1(cm)} cm`,\n });\n }\n if (kind === 'jump-rope') {\n items.push({ label: 'Jumps', value: String(live.jumps ?? 0) });\n if (live.elapsedS !== undefined) items.push({ label: 'Time', value: clockOf(live.elapsedS) });\n }\n if (kind === 'treadmill') {\n if (live.speedKmh !== undefined) items.push({ label: 'Speed', value: `${round1(live.speedKmh)} km/h` });\n if (live.distanceM !== undefined) items.push({ label: 'Distance', value: `${round1(live.distanceM / 1000)} km` });\n if (live.kcal !== undefined) items.push({ label: 'Calories', value: `${Math.round(live.kcal)} kcal` });\n if (live.elapsedS !== undefined) items.push({ label: 'Time', value: clockOf(live.elapsedS) });\n }\n if (kind === 'ring') {\n if (live.bpm !== undefined) items.push({ label: 'Heart rate', value: `${live.bpm} bpm` });\n if (live.spo2 !== undefined) items.push({ label: 'Blood oxygen', value: `${live.spo2}%` });\n if (live.skinTempC !== undefined) items.push({ label: 'Skin temp', value: `${round1(live.skinTempC)} °C` });\n if (live.steps !== undefined) items.push({ label: 'Steps', value: String(live.steps) });\n }\n if (live.battery !== undefined) items.push({ label: 'Battery', value: `${live.battery}%` });\n return (\n <View style={[styles.card, styles.livePanel, { backgroundColor: colors.surface }]}>\n <View style={styles.compositionGrid}>\n {items.map((m) => (\n <View key={m.label} style={styles.compositionItem}>\n <Text style={[styles.compositionLabel, { color: colors.textMuted }]}>{m.label}</Text>\n <Text style={[styles.compositionValue, { color: colors.text }]}>{m.value}</Text>\n </View>\n ))}\n </View>\n </View>\n );\n}\n\nfunction LivePanel({\n kind,\n colors,\n live,\n units,\n recording,\n connected,\n onStart,\n onStop,\n onSave,\n}: {\n kind: DeviceKindId;\n colors: Colors;\n live: LiveValue;\n units: 'metric' | 'imperial';\n recording?: { startedAt: number; workoutType: string; avgHr?: number; maxHr?: number };\n connected: boolean;\n onStart: (type: string) => void;\n onStop: () => void;\n onSave: () => void;\n}) {\n const [type, setType] = useState('run');\n if (kind === 'scale') {\n return <ScaleMeasuring colors={colors} live={live} units={units} />;\n }\n if (kind === 'kitchen-scale' || kind === 'tape' || kind === 'jump-rope' || kind === 'treadmill' || kind === 'ring') {\n return <BrandLive kind={kind} colors={colors} live={live} units={units} />;\n }\n const [, tick] = useState(0);\n useEffect(() => {\n if (!recording) return undefined;\n const t = setInterval(() => tick((n) => n + 1), 1000);\n return () => clearInterval(t);\n }, [recording]);\n if (kind === 'heart-rate') {\n const elapsed = recording ? Math.max(0, Math.floor((Date.now() - recording.startedAt) / 1000)) : 0;\n return (\n <View style={[styles.card, styles.livePanel, { backgroundColor: colors.surface }]}>\n <Text\n style={[styles.liveValue, { color: colors.text }]}\n accessibilityLabel={`Heart rate ${live.bpm ?? 0} beats per minute`}\n >\n {live.bpm ?? '--'}\n <Text style={[styles.liveUnit, { color: colors.textMuted }]}> bpm</Text>\n </Text>\n {recording ? (\n <>\n <Text style={[styles.liveMeta, { color: colors.textMuted }]}>\n {clockOf(elapsed)} · average {recording.avgHr ?? '--'} · max {recording.maxHr ?? '--'}\n </Text>\n <PrimaryButton label=\"Stop and save\" onPress={onStop} />\n </>\n ) : null}\n {!recording && connected ? (\n <>\n <View style={styles.chips}>\n {WORKOUT_TYPES.map((w) => (\n <Pressable\n key={w.id}\n onPress={() => setType(w.id)}\n accessibilityRole=\"radio\"\n accessibilityState={{ selected: type === w.id }}\n style={[\n styles.chip,\n { borderColor: type === w.id ? colors.primary : colors.border },\n type === w.id && { backgroundColor: colors.primarySoft },\n ]}\n >\n <Text\n style={[\n styles.chipLabel,\n { color: type === w.id ? colors.primary : colors.text },\n ]}\n >\n {w.label}\n </Text>\n </Pressable>\n ))}\n </View>\n <PrimaryButton label=\"Start session\" onPress={() => onStart(type)} />\n </>\n ) : null}\n </View>\n );\n }\n return (\n <View style={[styles.card, styles.livePanel, { backgroundColor: colors.surface }]}>\n <Text style={[styles.liveValue, { color: colors.text }]}>\n {live.spo2 ?? '--'}\n <Text style={[styles.liveUnit, { color: colors.textMuted }]}>%</Text>\n </Text>\n <Text style={[styles.liveMeta, { color: colors.textMuted }]}>\n Blood oxygen{live.pulse ? ` · pulse ${live.pulse}` : ''}\n </Text>\n {connected ? <PrimaryButton label=\"Save this reading\" onPress={onSave} /> : null}\n </View>\n );\n}\n\nfunction Measure({\n kind,\n deviceId,\n colors,\n units,\n onDone,\n onHealth,\n}: {\n kind: DeviceKindId;\n deviceId?: string;\n colors: Colors;\n units: 'metric' | 'imperial';\n onDone: () => void;\n onHealth: () => void;\n}) {\n const { snapshot, session } = useDeviceSession(kind, deviceId);\n const { state, readings, live, recording, notices } = snapshot;\n const info = deviceKind(kind);\n const now = Date.now();\n const retry = () => {\n void session?.start();\n };\n\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n {state.step === 'starting' ? <ActivityIndicator style={styles.loading} color={colors.primary} /> : null}\n\n {state.step === 'unavailable' ? (\n <Notice colors={colors} tone=\"warning\" icon=\"information-circle\" text={state.reason} />\n ) : null}\n\n {state.step === 'radio' ? (\n <View style={styles.center}>\n <BluetoothPulse colors={colors} active={false} />\n <Text style={[styles.statusTitle, { color: colors.text }]}>{radioCopy(state.radio).title}</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>{radioCopy(state.radio).body}</Text>\n {state.radio === 'unauthorized' ? (\n <PrimaryButton\n label=\"Open Settings\"\n onPress={() => {\n void Linking.openSettings();\n }}\n />\n ) : null}\n {state.radio === 'off' ? <PrimaryButton label=\"Try again\" onPress={retry} /> : null}\n </View>\n ) : null}\n\n {state.step === 'scanning' ? (\n <>\n <BluetoothPulse colors={colors} active />\n <Text style={[styles.statusTitle, { color: colors.text }]}>\n {deviceId ? 'Looking for your device' : 'Looking for devices nearby'}\n </Text>\n <View style={[styles.card, styles.guidance, { backgroundColor: colors.surface }]}>\n {info.steps.map((line, i) => (\n <View key={line} style={styles.guidanceRow}>\n <View style={[styles.stepDot, { backgroundColor: colors.primarySoft }]}>\n <Text style={[styles.stepNumber, { color: colors.primary }]}>{i + 1}</Text>\n </View>\n <Text style={[styles.guidanceText, { color: colors.text }]}>{line}</Text>\n </View>\n ))}\n </View>\n {state.hint ? (\n <Notice\n colors={colors}\n tone=\"warning\"\n icon=\"information-circle\"\n text={`Nothing yet. ${state.hint} Keep it close to the phone.`}\n />\n ) : null}\n {state.found.length ? (\n <>\n <Text style={[styles.sectionTitle, { color: colors.textMuted }]}>NEARBY</Text>\n <View style={[styles.card, { backgroundColor: colors.surface }]}>\n {state.found.map((f, i) => (\n <FoundRow\n key={f.id}\n found={f}\n first={i === 0}\n colors={colors}\n onPress={() => {\n void session?.pick(f);\n }}\n />\n ))}\n </View>\n </>\n ) : null}\n </>\n ) : null}\n\n {state.step === 'connecting' ? (\n <View style={styles.center}>\n <ActivityIndicator color={colors.primary} size=\"large\" />\n <Text style={[styles.statusTitle, { color: colors.text }]}>Connecting to {state.device.name}</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>\n If your phone asks to pair, tap Pair.\n </Text>\n </View>\n ) : null}\n\n {state.step === 'connected' && !readings.length && !live ? (\n <View style={styles.center}>\n <BluetoothPulse colors={colors} active connected />\n <Text style={[styles.statusTitle, { color: colors.text }]}>{info.waitingFor}</Text>\n <Text style={[styles.statusBody, { color: colors.textMuted }]}>\n Connected to {state.device.name}.\n </Text>\n </View>\n ) : null}\n\n {(state.step === 'connected' || state.step === 'ended') && live ? (\n <LivePanel\n kind={kind}\n colors={colors}\n live={live}\n units={units}\n recording={recording}\n connected={state.step === 'connected'}\n onStart={(type) => session?.startRecording(type)}\n onStop={() => {\n void session?.stopRecording();\n }}\n onSave={() => {\n void session?.saveLive();\n }}\n />\n ) : null}\n\n {notices.map((n) => (\n <Notice key={n} colors={colors} tone=\"warning\" icon=\"information-circle\" text={n} />\n ))}\n\n {readings.length ? (\n <ReadingsCard title=\"JUST MEASURED\" readings={readings} colors={colors} units={units} now={now} />\n ) : null}\n {readings.length ? <SavedLine colors={colors} onHealth={onHealth} /> : null}\n\n {state.step === 'ended' ? (\n <View style={styles.actions}>\n {!readings.length ? (\n <Text style={[styles.actionHint, { color: colors.textMuted }]}>\n The device went to sleep before it sent a measurement.\n </Text>\n ) : null}\n <PrimaryButton label=\"Done\" onPress={onDone} />\n <SecondaryButton label=\"Measure again\" colors={colors} onPress={() => session?.scan()} />\n </View>\n ) : null}\n\n {state.step === 'connected' && readings.length ? (\n <View style={styles.actions}>\n <PrimaryButton label=\"Done\" onPress={onDone} />\n </View>\n ) : null}\n\n {state.step === 'error' ? (\n <View style={styles.center}>\n <Ionicons name=\"alert-circle\" size={40} color={colors.dangerText} />\n <Text style={[styles.statusTitle, { color: colors.text }]}>{state.message}</Text>\n <PrimaryButton label=\"Try again\" onPress={retry} />\n </View>\n ) : null}\n </ScrollView>\n );\n}\n\n// ------------------------------------------------------------ Device detail\n\nfunction DeviceDetail({\n id,\n colors,\n units,\n onMeasure,\n onForgot,\n}: {\n id: string;\n colors: Colors;\n units: 'metric' | 'imperial';\n onMeasure: (kind: DeviceKindId) => void;\n onForgot: () => void;\n}) {\n const devices = useDevices();\n const device = devices.devices.find((d) => d.id === id);\n const readings = useMemo(\n () =>\n devices.readings\n .filter((r) => r.deviceId === id)\n .sort((a, b) => b.at - a.at)\n .slice(0, 20),\n [devices.readings, id],\n );\n if (!device) return null;\n const forget = () =>\n Alert.alert(`Forget ${device.name}?`, 'Its readings stay in Yantra. To use it again, pair it again.', [\n { text: 'Cancel', style: 'cancel' },\n {\n text: 'Forget',\n style: 'destructive',\n onPress: () => {\n void deviceStore.forget(id).then(onForgot);\n },\n },\n ]);\n return (\n <ScrollView contentContainerStyle={styles.scroll}>\n <View style={styles.hero}>\n <KindIcon kind={device.kind} colors={colors} large />\n <Text style={[styles.heroTitle, { color: colors.text }]}>{device.name}</Text>\n <Text style={[styles.heroBody, { color: colors.textMuted }]}>\n {deviceKind(device.kind).title}\n {device.scaleUser ? ` · user ${device.scaleUser.userIndex} on this scale` : ''}\n </Text>\n </View>\n <View style={styles.actions}>\n <PrimaryButton\n label={device.kind === 'heart-rate' ? 'Start a session' : 'Take a reading'}\n onPress={() => onMeasure(device.kind)}\n />\n </View>\n {readings.length ? (\n <ReadingsCard title=\"READINGS\" readings={readings} colors={colors} units={units} now={Date.now()} />\n ) : (\n <Text style={[styles.footnote, { color: colors.textMuted }]}>No readings from this device yet.</Text>\n )}\n <View style={[styles.card, styles.secondaryCard, { backgroundColor: colors.surface }]}>\n <Pressable\n onPress={forget}\n accessibilityRole=\"button\"\n style={({ pressed }) => [styles.row, pressed && { backgroundColor: colors.surfaceMuted }]}\n >\n <Text style={[styles.rowLabelWide, { color: colors.dangerText }]}>Forget this device</Text>\n </Pressable>\n </View>\n </ScrollView>\n );\n}\n\nexport default function DevicesScreen() {\n const navigation = useNavigation<NavigationProp<ParamListBase>>();\n const route = useRoute<RouteProp<Record<string, DevicesParams>, string>>();\n const { isDark } = useAppTheme();\n const colors = mobileColors(isDark);\n const insets = useSafeAreaInsets();\n const devices = useDevices();\n const [stack, setStack] = useState<Step[]>(() =>\n route?.params?.add ? [{ name: 'home' }, { name: 'pick' }] : [{ name: 'home' }],\n );\n const step = stack[stack.length - 1];\n const units = devices.person?.units ?? 'metric';\n\n const orgName = useMemo(() => {\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params?.orgName]);\n\n const push = useCallback((next: Step) => setStack((s) => [...s, next]), []);\n const pop = useCallback(() => {\n if (stack.length > 1) {\n setStack((s) => s.slice(0, -1));\n return true;\n }\n if (navigation?.canGoBack?.()) {\n navigation.goBack();\n return true;\n }\n navigation?.dispatch?.(\n CommonActions.navigate({ name: 'MainStack.Account', params: orgName ? { orgName } : undefined }),\n );\n return true;\n }, [stack.length, navigation, orgName]);\n\n useEffect(() => {\n const sub = BackHandler.addEventListener('hardwareBackPress', pop);\n return () => sub.remove();\n }, [pop]);\n\n const openHealth = useCallback(() => {\n navigation?.navigate?.('MainStack.Health', orgName ? { orgName } : undefined);\n }, [navigation, orgName]);\n\n const title = stepTitle(step, devices.devices);\n\n return (\n <SafeAreaView edges={['top', 'left', 'right']} style={[styles.safe, { backgroundColor: colors.bg }]}>\n <View style={[styles.header, { paddingTop: insets.top > 0 ? 4 : 10 }]}>\n <Pressable\n onPress={pop}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Go back\"\n style={({ pressed }) => [\n styles.backCircle,\n { backgroundColor: colors.surface },\n pressed && styles.pressed,\n ]}\n >\n <Ionicons name=\"chevron-back\" size={22} color={colors.text} />\n </Pressable>\n <Text style={[styles.headerTitle, { color: colors.text }]} numberOfLines={1}>\n {title}\n </Text>\n <View style={styles.headerSpacer} />\n </View>\n {step.name === 'home' ? (\n <Home\n colors={colors}\n isDark={isDark}\n units={units}\n onAdd={() => push({ name: 'pick' })}\n onOpen={(id) => push({ name: 'device', id })}\n onHealth={openHealth}\n />\n ) : null}\n {step.name === 'pick' ? (\n <PickKind colors={colors} isDark={isDark} onPick={(kind) => push({ name: 'measure', kind })} />\n ) : null}\n {step.name === 'measure' ? (\n <Measure\n key={`${step.kind}:${step.deviceId ?? ''}`}\n kind={step.kind}\n deviceId={step.deviceId}\n colors={colors}\n units={units}\n onDone={() => setStack([{ name: 'home' }])}\n onHealth={openHealth}\n />\n ) : null}\n {step.name === 'device' ? (\n <DeviceDetail\n id={step.id}\n colors={colors}\n units={units}\n onMeasure={(kind) => push({ name: 'measure', kind, deviceId: step.id })}\n onForgot={() => setStack([{ name: 'home' }])}\n />\n ) : null}\n </SafeAreaView>\n );\n}\n"],"names":["React","_a","_b"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminide-stack/yantra-mobile",
3
- "version": "12.0.142-alpha.0",
3
+ "version": "12.0.142",
4
4
  "description": "Sample core for higher packages to depend on",
5
5
  "license": "ISC",
6
6
  "author": "CDMBase LLC",
@@ -27,7 +27,7 @@
27
27
  "uuid": "^9.0.0"
28
28
  },
29
29
  "devDependencies": {
30
- "common": "12.0.141-alpha.1",
30
+ "common": "12.0.141",
31
31
  "libphonenumber-js": "^1.13.3"
32
32
  },
33
33
  "peerDependencies": {
@@ -45,7 +45,7 @@
45
45
  "@messenger-box/platform-mobile": "*",
46
46
  "@react-native-async-storage/async-storage": "*",
47
47
  "@react-navigation/native": "*",
48
- "common": "12.0.141-alpha.1",
48
+ "common": "12.0.141",
49
49
  "expo-background-task": "*",
50
50
  "expo-constants": "*",
51
51
  "expo-secure-store": "*",
@@ -67,5 +67,5 @@
67
67
  "typescript": {
68
68
  "definition": "lib/index.d.ts"
69
69
  },
70
- "gitHead": "7078dd4c263310ce67da5330280e52c322429da9"
70
+ "gitHead": "80980b8e928ffa364accf4aa00afa3a0d18b1ce1"
71
71
  }