Skip to content

Local-first revamp: design system, AI briefings, custom icons, splash + reliability - #38

Merged
abdulsaheel merged 15 commits into
mainfrom
feat/edge-revamp
Jul 7, 2026
Merged

Local-first revamp: design system, AI briefings, custom icons, splash + reliability#38
abdulsaheel merged 15 commits into
mainfrom
feat/edge-revamp

Conversation

@abdulsaheel

Copy link
Copy Markdown
Collaborator

Summary

A broad revamp of the Edge app. Tests green (~343), flutter analyze at baseline, debug APK builds.

UI

  • New light + dark design system — one semantic token set, a single font (Manrope, tabular figures), real depth + a shared motion language.
  • Full screen revamp on that system — bento layouts, numbers-first with explanations behind (i)/tap, both themes first-class, a floating nav pill, and the custom illustrated icon pack (openstrap_icons) wired across nav, domains, and metrics.

AI (bring-your-own-key, text)

  • Morning + evening briefings → notification → a shared breakdown screen.
  • Pre-sleep journaling (manual entry or an AI chat that writes structured entries).

Reliability + data

  • Boot splash video (plays during init, dismisses the instant the app is ready).
  • Working alarm (real payload) with event-based confirmation.
  • BLE: foreground catch-up sync, background HR-only streaming, honest last-data, bond give-up detector, archive-before-trim, grid-snapped RTC correction, battery-health series.
  • Android: CompanionDeviceManager presence, sticky foreground service, battery-optimization flow, background location for GPS routes.
  • Data: workout HR/zones/HRR enrichment, real records + per-zone minutes, today's HR clipped to today, GPS route-tracker gap recovery, restored iOS edge-swipe-back.

Notes

  • Depends on the sibling protocol, analytics, and icons packages (git refs).
  • iOS needs pod install before its next build (adds video_player).

abdulsaheel and others added 10 commits July 3, 2026 03:40
… splash, reliability + data fixes

UI: a new light+dark design system (single token set, one font, motion) and a
full bento-composed revamp of every screen (numbers-first, detail behind (i)/tap),
a floating nav pill, and the custom illustrated icon pack wired throughout.

AI (BYOK, text): morning + evening briefings -> notification -> a shared
breakdown screen, plus pre-sleep journaling (manual + AI chat).

Boot splash video that plays during init and dismisses the instant the app is
ready. Working strap alarm (real payload) with event-based confirmation.

BLE reliability: foreground catch-up sync, background HR-only to avoid starving
the flash flush, honest last-data, bond give-up detector, archive-before-trim,
grid-snapped RTC correction; battery-health series; Android CDM presence +
sticky foreground service + battery-optimization flow.

Data fixes: getWorkout HR/zones/HRR enrichment, real records + per-zone minutes,
today HR clipped to today, GPS route-tracker gap recovery, Android background
location, restored iOS edge-swipe-back.
… the revamp

Integrates the historical-sync reliability work (per-revision packet counts,
intra/cross-burst gap detection against the HISTORY_END expected count, honest
raw SpO2 logging, band-ownership lease + high-frequency wake window, boot
signal, advanced-data and data-history screens) with the app revamp (design
system, RecordGate single ingest path, archive-before-trim, bond give-up,
foreground catch-up, HR-only background live, CDM association, alarm, GPS).

Notable reconciliations:
- decoded_onehz is the durable substrate (raw_records dropped); raw_archive
  keeps undecodable records forever, committed before the batch-ACK.
- One shared _ingestHistoricalFrame path feeds both the RecordGate and the
  per-burst packet accounting; HPS terminals recorded on out-of-sync bursts.
- openSession/reconnect keep live+drain concurrent, with the high-frequency
  wake window armed on connect and re-evaluated after the backlog lands.
- BackfillContinuation keeps the rows-persisted gate (#451 stale newest).
- Profile gains Data history + debug-gated Advanced data entries; Today gains
  the stale-data status card alongside the settling chip.
- DB version 22 (raw_archive + battery millivolts, workout_route).
abdulsaheel and others added 5 commits July 6, 2026 00:19
Fixes a persistent "last data > 1hr behind" regression: the freshness
signal only ever read decoded_onehz's max timestamp (misses R10-lite
records) and only ever refreshed at app boot; now reads the rec_ts_hw
sync cursor and refreshes on every successful persist (onDataStored),
foreground or background. Also makes HISTORY_END packet-count
validation advisory instead of a hard gate — a mismatch used to
discard an entire buffered chunk and re-request it forever, since the
band's reported count and our tally don't have fully-confirmed
semantics; every buffered record already passed CRC32 + plausibility
checks, so a count mismatch was never real evidence of bad data.

UI/UX: Profile screen gets a working back button (AppScaffold) and
drops decorative icons + the Storage section; Today screen fixes a
list-reflow glitch behind the freshness banner (stable keys) and adds
context to the weekly steps card; MetricRow drops its per-row icon
(icon spam) and fixes numeric clipping (FittedBox, never ellipsis);
Journey/Timeline merge into one multi-vital lookback; workout-type
icons wired through a new shared workout_types.dart seam.
fix: sync-freshness banner, burst validation, and UI/UX polish
Two independent release-pipeline breaks traced to this: a newer stable
removed/moved CupertinoPageTransitionsBuilder (theme.dart failed to
compile on Android), and changed how --no-codesign propagates to the
Watch companion target (iOS build demanded a signing team despite
--no-codesign). Verified 3.41.6 builds both platforms clean locally.
…ompanion bundle id

Closes out the branch's outstanding work for the edge revamp:

- iOS BLE background: fix the two real gaps behind "strap disconnects and
  never reconnects in background" — a zombie-link blind spot in the
  BGAppRefreshTask/BGProcessingTask catch-up path (foregroundCatchUp now
  checks staleness via a shared isLinkStale policy instead of trusting a
  possibly-dead "connected" flag), and a two-call race in the iOS restore
  hand-off (_armRecovery now arms atomically in one native round trip via
  BleRestoreManager.armRecoveryNow, wrapped in a background-task extension).
- Restore ListRow's two-field icon design (monochrome `icon` via AppIcon vs
  illustrated `osIcon` via OsAppIcon) after a rushed openstrap_icons API fix
  collapsed both into one field and force-unwrapped it, crashing every
  icon-less row (this is what showed up as a grey bar swallowing the Profile
  screen). Same leftover debug pattern cleaned up in coach_screen.dart.
  Wired the illustrated header icon back onto Steps/Stress/Calories tiles.
- ios/Runner.xcodeproj: WKCompanionAppBundleIdentifier was hardcoded to a
  literal bundle id instead of deriving from $(APP_BUNDLE_IDENTIFIER) like
  every other identifier in the project — invisible under a normal Xcode
  build (personal signing happens to match), but breaks any post-hoc
  resign (e.g. Sideloadly) that rewrites the bundle id without knowing to
  patch this literal too.

Also carries forward the rest of this branch's in-progress work (route
tracker stall-watchdog + injectable clock, units controller, misc UI).

All 389 tests green, flutter analyze clean on every touched file.
@abdulsaheel
abdulsaheel merged commit d70cc5e into main Jul 7, 2026
abdulsaheel added a commit that referenced this pull request Jul 7, 2026
Local-first revamp (design system, AI briefings, custom icons, splash),
GPS workout routes, and the iOS BLE background-reliability + icon-wiring
fixes from PR #38 — bump build 18 -> 19.
@abdulsaheel abdulsaheel mentioned this pull request Jul 7, 2026
@abdulsaheel
abdulsaheel deleted the feat/edge-revamp branch July 12, 2026 05:53
svssathvik7 added a commit to svssathvik7/edge that referenced this pull request Aug 6, 2026
kAlgoVersion 55 and 56 both cite the new nap detector as their sibling change,
and until this commit neither was backed by the pin. pubspec.yaml still pointed
at OpenStrap#34 (f0d1153), which has no `sleep/nap.dart`, no `wristOff:`/`exclude:` on
`detectNaps`, and no `tstSec`/`tibSec`/`efficiency` on `NapWindow`.

This is the §3.5 failure mode the v43 changelog is remembered for, except worse
in kind: v43 shipped a changelog describing a fix its pin merely lacked, while
this branch did not COMPILE against its own pin — 10 analyzer errors in
derivation_engine.dart. It went unnoticed because pubspec_overrides.yaml is
gitignored and resolves both siblings to local working copies, so every local
build and test run silently used analytics HEAD rather than the pinned SHA.
Confirmed by moving the override aside and running `flutter pub get` against
the real pin.

Verified present at c3a30be, per §3.5:
  git show c3a30be:lib/src/onehz/sleep/nap.dart | grep -cE 'wristOff|exclude|tibSec'   -> 16
  git show c3a30be:lib/src/onehz/sleep/van_hees.dart | grep -c immobilityMask          -> 2

pubspec.lock regenerated with the override moved aside, so it locks the git SHA
rather than `path: ../analytics`. A path-source lock fails CI `flutter pub get`
(exit 66) and is the reason that file must never be regenerated with the
override in place.

No kAlgoVersion bump: 56 is already the version describing this analytics
behaviour, and it has not shipped. The pin and the version now land together,
which is the whole point.

Against the real pin: flutter analyze lib/ clean, 1150 tests pass. The single
failure is workout_reliability_test.dart's queued-job case, pre-existing and
identical on clean main.
abdulsaheel added a commit that referenced this pull request Aug 7, 2026
Five conflicted files, all reconciled to keep BOTH sides' intent rather than
picking a winner.

kAlgoVersion / changelog. Both branches wrote a v55 and a v56 with different
content: main's are the nap + strain work (#204), this branch's are the step
and movement-minute rebuild. Main's stay as history; this branch's three
entries are renumbered 55/56/57 -> 57/58/59 and the constant becomes 59.
Strict monotonicity is load-bearing, not cosmetic -- the derive gate matches
algo_version EXACTLY while the read seam serves MAX(algo_version), so a version
that goes backwards writes rows nobody reads and re-derives forever.

Note: git had silently DROPPED this branch's v57 entry (the absent-steps
tier/labelling follow-up) when resolving the overlapping tail toward main. It
is restored here as v59; the code it documents was never lost, only its
changelog.

Analytics pin. Neither side was right: HEAD had #35's PR-BRANCH head (38a8636,
never on main) and main had the older #38 merge (c3a30be). Now 1fb34dce =
analytics main @ #35 merge, which carries all three hops this release needs --
#38 (nap detector), #39 (the awake-HR baseline P0 that shipped inside #38), and
#35 (the sibling half of THIS branch). Verified against the SHA: absent
`dailyStepEstimate`, present `dailyActiveMinutes`.

Health export delete list. The two intents compose rather than conflict, so
`_rewriteTypes` is now `healthDeleteTypes(isApplePlatform:)` MINUS STEPS:
  * main's helper drops the sleep types and HEART_RATE on Android, where the
    native SleepSessionRecord writer and the minute-HR batch own their cleanup;
  * STEPS comes off on top, because nothing writes steps any more -- deleting a
    type we never write would run on every re-export of the not-yet-finalized
    tail forever, and a false `delete()` flips `success`, so it could stall a
    day's export cursor permanently. The historical fabricated samples are
    handled once by `_purgeLegacyStepsIfNeeded`, outside success accounting.
Also kept main's Android sleep-session write alongside this branch's one-shot
purge, and kept this branch's removal of the steps EXPORT (writing our derived
copy back would double-count against the phone's own HealthKit pedometer rows,
which we now read).

healthSyncNow. Composed: the export runs through main's single-flight guard,
and the phone-steps sync stays gated on `phoneStepsEnabled`.

flutter analyze clean; full suite 1324 passing, 0 failing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants