Repository navigation
OpenVitals 2.0.4
github-actions[bot] edited this page Nov 9, 2026
·
1 revision
Released 2026-07-12.
The app's insides were rebuilt this release, and the rebuild is what found the bugs. Moving every calculation out of the screens that were doing it mid-draw put a lot of arithmetic side by side for the first time — and several numbers, it turned out, disagreed with each other.
- The sleep card called your watch's recordings "hand-typed", and never noticed the ones that really were. Health Connect labels how a record was made — actively recorded, automatically recorded, typed in by a person — and the data-confidence card was comparing that label against the wrong value. So it warned you about manual entries whenever your watch had recorded the night properly, and a night you genuinely did type in was never counted at all. The number the app was checking against is not one the app gets to choose; it is now written down once, in one place, rather than copied into three files where one of them was wrong.
- The hydration goal bar filled up if you logged a single day. It measured the average of the days you logged against your goal — so a week in which you logged Monday, hit your target, and never opened the app again showed a completely full bar, with "1 of 1 days met" written above it. Log nothing and you cannot fall short of anything. The bar now counts the days you met your goal against the days that have actually happened, and stops at today: a goal you have not yet had the chance to miss does not count against you.
- A day's heart rate could print an average outside its own low and high. The average came from Health Connect's own summary of the day, while the low and the high came from the individual readings — two different sets of numbers, printed side by side as though they were one. All three now come from the readings.
- The skin-temperature card went blank while its own chart carried on drawing. A reading that arrives without a temperature difference emptied the card, while the chart directly underneath it went on plotting the readings that had one. The card and the chart now look at the same readings.
- Respiratory rate showed you two different averages on one screen, and told you neither which was which: the figure under the chart was the average of your days, the figure on the card below it was the average of every individual reading. On an unevenly sampled week those are different numbers. There is one now.
- An Apple Health import that failed on permissions said nothing useful, and offered no way to fix it. The one button that would have solved the problem — "grant permission" — could never appear, because a permission failure was never reported as one. It is now.
- Screens could spin forever after a failed permission check. On the dashboard, in onboarding, and while saving an activity, a Health Connect permission probe that failed threw its error where nothing was listening. The loading spinner simply never stopped. Each of them now tells you what went wrong.
- The app was rebuilt to Flutter's app-architecture guidelines. Every screen now works out what to show once, when its data loads, instead of recalculating charts, totals and statistics on every single redraw while you scroll. This is invisible if it went well, which is the point — but it is also why the fixes above exist, and it is the groundwork for iOS. The automated test suite grew from 1,605 checks to 1,890 in the process.
The app keeps the same package name and signing certificate, so this installs as a normal update.
Distribution flow:
- Codeberg release with signed APK and signed Android App Bundle assets.
- Direct Google Play production upload from the approved Woodpecker deployment.
Generated from docs/releases/2.0.4.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