Repository navigation
Body Metrics
Status: Current implemented behavior. Audience: Users and contributors. Implementation:
features/body,features/manualentry/body,data/repository/BodyRepository.kt. Navigation:Screen.Metric, body entry routes; widgetsWEIGHT,HEIGHT,BMI,FFMI,BODY_FAT,LEAN_MASS,BMR,BONE_MASS,BODY_WATER_MASS. Related: Feature map, Manual entry of metrics, Statistics.
The body feature owns period-based detail screens for body measurement and composition metrics read from Health Connect.
Each body dashboard tile opens its own focused metric screen directly - tapping Weight opens the weight detail, not an intermediate Body overview.
Body metric detail screens currently cover:
- Weight.
- Height.
- BMI.
- FFMI.
- Body fat.
- Lean mass.
- Basal metabolic rate.
- Bone mass.
- Body water mass.
BMI and FFMI-style context are derived from available measurements. Derived values should explain missing prerequisites instead of pretending the calculation is complete.
FFMI is derived, not read. The screen's headline is the dashboard tile's value: adjusted FFMI from the latest weight, body fat and height on record.
Its history (chart, statistics, entries) has one reading per body-fat measurement in the period, paired with the weight nearest it in time, which may sit just across the period's edge. A weigh-in with no body-fat reading adds no point: carrying an old body-fat percentage onto later weights would show fat lost as lean mass lost. Height is the latest on record, as BMI uses it. The readings are calculated, so their rows edit nothing.
Settings, Body profile holds a weight and a height alongside birth year and heart-rate values, and they are the same numbers the body metrics use.
- When Health Connect has a recorded measurement, the field shows that value and is labelled as measured.
- Changing the weight or the height also writes it to Health Connect as a real measurement, so the app does not hold a second private copy of a number it already has. Saving an unchanged card writes nothing, so opening the section repeatedly does not litter the body history.
- When nothing has been recorded, or the app cannot write body measurements, the typed value is kept as a local preference and used the same way.
Either way there is one weight and one height, so BMI, FFMI context, Body Energy, and caffeine estimates all agree. See Settings and preferences.
Off by default. Settings, Body profile has a "Basal metabolic rate" switch. On, OpenVitals estimates the resting daily burn with Mifflin-St Jeor from the profile's sex, birth year, weight and height, and writes one BasalMetabolicRateRecord per day to Health Connect.
- It is a writer like the step-distance backfill (
data/sync/BmrEstimateService.kt,healthconnect/BmrEstimateHealthReader.kt): it runs as the last history drain after app open, and at once when the switch or the profile changes. - It covers the last 90 days. Each day uses the weight measured on or before it, falling back to the declared profile weight, so an old day is not rewritten with today's weight.
- A day that already has a rate from any other source, a watch import or a CSV row included, is left alone, and a rate that arrives later evicts the estimate for that day.
- Its records carry the
openvitals_bmr_<date>client record id; nothing else is ever deleted. Switching off removes them all, and a purge that could not finish is retried by the next pass. - The card names which profile inputs are still missing; until they are all there nothing is written. The sex field exists only for this formula.
Body metrics follow the canonical period-detail pattern:
- Day, week, month, and year ranges.
- Previous/next period navigation capped at the current period.
- Calendar selection and pull to refresh.
- Period charts, selected-day entries, statistics, comparisons, personal baselines, and data confidence.
- Week, month and year draw a trend line over a fitted scale; only Day uses the intraday chart.
- Entry lists that allow edit/delete only for OpenVitals-created records.
- Reorderable metric detail sections.
Manual body entry lives under features/manualentry/body and writes explicit user-entered records to Health Connect. The dashboard and body detail screens remain read-oriented.
Month and year used to hand these metrics to the calendar heatmap, which colours each day by how big its number is. That reads well for a quantity that can be zero and can be huge — steps, minutes — and reads as nothing at all for one that spends its life inside a two-kilo band. Forty dots of near-identical colour answered "did you weigh yourself on the 14th" while hiding the only thing the screen is opened for, which is which way the line is going.
Body measurements are levels, not accumulations, so they now draw the same trend line the heart and vitals screens have always drawn for the same shape of data. The y axis is fitted to the values rather than anchored at zero, because a kilogram of drift is invisible on a scale that starts at nothing.
Day keeps its own intraday chart, where the x axis is hours rather than dates.
The body feature reads through BodyRepository. New body metric work should keep feature-specific formatting, cards, charts, and rows in features/body; shared components should only move out when another feature really reuses them.
Generated from docs/features/body-metrics.md. Edit it there; changes made here are overwritten.
This wiki mirrors the Markdown in Hale-MTU/OpenVitals on every push to main.
Features
- Features
- Achievements
- Activity And Training Plans
- Activity Metrics
- Apple Health Import
- Beverage Logging And Caffeine
- Bluetooth LE Sensors
- Body Energy
- Body Metrics
- CoMaps Navigation Context
- CSV Import
- Cycle Tracking
- Daily Readiness
- Elevation Correction
- Feature Map
- FIT Files Import
- Food Logging
- GPX/KML/KMZ/TCX Route Import
- Health Connect Metrics Dashboard
- Health Report Export
- Heart And Vitals
- Heart Rate Recovery
- Home Screen Widgets
- Hydration
- Manual Entry Of Metrics
- Medical Records
- Metric Detail Customization
- Mindfulness
- Non Health Connect Metrics Dashboard
- Nutrition
- Offline Maps Support
- Onboarding And Permissions
- Preloaded Beverage Nutrition Reference
- Privacy, Support, And Diagnostics
- Recording Of Activity
- Reminders
- Settings And Preferences
- Sleep Score And Recovery
- Sleep Tracking
- Statistics
- Sync With Another Phone
How-to
App
- App Guide
- FAQ
- Getting Started
- Health Connect
- Install
- Local And Connected Editions
- Permissions
- Privacy
- Screenshots
- Support
Reference
- Design Reference
- Reference
- Design Guidelines for Offline & Sync
- OpenVitals UI Notes
- Reference: Data Capture
- Reference: Data Display
- Reference: Health Connect Matchmaking
- Reference: Health Connect Onboarding
- Reference: Health Connect Permissions
- Reference: Health Connect UX
- Reference: Promoting Health Connect
Engineering
- Code Analysis
- Engineering
- Flutter ↔ Kotlin test-parity matrix
- apple-health-import
- Architecture
- body-cycle-recovery
- Design system conformance
- Development
- Feature Playbook
- Flutter -> Kotlin test parity: domain/data/core/contract/state/navigation/di/bootstrap/l10n/widget_test
- Flutter → Kotlin test-parity matrix: features section
- Flutter → Kotlin test-parity matrix: ui / goldens / integration / fixtures
- Flutter-to-Kotlin test-parity matrix — dashboard + devicesync
- manual-entry
- Translations
Proposals
- Proposals
- Activity Start Flow Analysis
- Activity Start Flow Simplification Proposals
- Caffeine Detail And Future Sleep Insights
- Cycle Tracking: Design and Status
- Medical Records Through Health Connect
- Medical Records: What Is Left
Releases
- OpenVitals 2.16.0
- OpenVitals 2.15.2
- OpenVitals 2.15.1
- OpenVitals 2.15.0
- OpenVitals 2.14.5
- OpenVitals 2.14.4
- OpenVitals 2.14.3
- OpenVitals 2.14.2
- OpenVitals 2.14.1
- OpenVitals 2.14.0
- OpenVitals 2.13.0
- OpenVitals 2.12.0
- OpenVitals 2.11.2
- OpenVitals 2.11.1
- OpenVitals 2.11.0
- OpenVitals 2.10.1
- OpenVitals 2.10.0
- OpenVitals 2.9.1
- OpenVitals 2.9.0
- OpenVitals 2.8.0
- OpenVitals 2.7.3
- OpenVitals 2.7.2
- OpenVitals 2.7.1
- OpenVitals 2.7.0
- OpenVitals 2.6.6
- OpenVitals 2.6.5
- OpenVitals 2.6.4
- OpenVitals 2.6.3
- OpenVitals 2.6.2
- OpenVitals 2.6.1
- OpenVitals 2.6.0
- OpenVitals 2.5.0
- OpenVitals 2.4.1
- OpenVitals 2.4.0
- OpenVitals 2.3.2
- OpenVitals 2.3.1
- OpenVitals 2.3.0
- OpenVitals 2.2.8
- OpenVitals 2.2.7
- OpenVitals 2.2.6
- OpenVitals 2.2.5
- OpenVitals 2.2.4
- OpenVitals 2.2.3
- OpenVitals 2.2.2
- OpenVitals 2.2.1
- OpenVitals 2.2.0
- OpenVitals 2.1.0
- OpenVitals 2.0.4
- OpenVitals 2.0.3
- OpenVitals 2.0.2
- OpenVitals 2.0.1
- OpenVitals 1.9.0
- OpenVitals 1.8.0
- OpenVitals 1.7.7
- OpenVitals 1.7.6
- OpenVitals 1.7.5
- OpenVitals 1.7.4
- OpenVitals 1.7.3
- OpenVitals 1.7.2
- OpenVitals 1.7.1
- OpenVitals 1.7.0
- OpenVitals 1.6.3
- OpenVitals 1.6.2
- OpenVitals 1.6.1
- OpenVitals 1.6.0
- OpenVitals 1.5.1
- OpenVitals 1.5.0
Project