Conversation
Move the bottom navigation into a dedicated CarpAppShell and make the redesigned HomePage the landing tab, replacing StudyPage (kept as a redirect alias). The home page shows the study title, app-update and connection-status cards, and live days-in-study / tasks-completed stats from the deployment status and the user task queue. Tab switches now animate with a fade/scale transition; each tab page gets a unique page key so the transition actually runs. Informed consent moves to a root-level route so the bottom bar does not bleed through. DeviceViewModel bridges device status events into listener notifications, and nav bar labels are renamed to Home / Statistics / Connections.
All four tab pages render their title through a shared CarpPageTitle widget so font and padding stay consistent. The scoreboard on the tasks page is redundant now that the home page shows the same stats, so the card and its view-model getters are removed.
The profile page and the device connect flows (Bluetooth and Health) were pushed onto the shell's nested navigator, leaving the bottom navigation bar visible. Push them on the root navigator so they cover the whole screen.
Make the stat tiles compact (label + icon badge on top, value below, with a completed/total count on the tasks tile), slim the app-update banner down to a text row with a Get button, and add back a study status card showing the deployment state with its message. The deployment status is now refreshed once from the home view model - it was never fetched before, which kept the status card hidden and days-in-study at 0. The home page also reuses SurveyCard for a new Completed Surveys section; the card gets a showTitle flag so its internal header can be hidden under the page's section heading.
Adds informed-consent download to the profile page, reorders the shell tabs, and pins the app to the light theme until the dark palette is done.
CAWS returns invitations in no particular order, so the list reshuffled on every pull-to-refresh. Sort by study name, deployment id as tie-breaker. Logs are tagged INVITATIONS to trace duplicate entries.
# Conflicts: # pubspec.lock # pubspec.yaml
Messages are polled, not pushed, so a new announcement could sit unseen until the user happened to open the study page. Fire a local notification for every message id that was not in the previous refresh; the first refresh only records the backlog so opening the app stays quiet.
A participant invited to two deployments of the same study shares one participant id across both, so keying the detail route on it made the second card open the first deployment. Use the study deployment id, the only id unique per invitation. Leaving a study no longer clears the invitation list either - invitations belong to the account, not the study, and clearing them left the list page spinning forever on a state nothing reloaded.
Consent was a router redirect target, so it was always the only route on the stack: research_package pops that route itself on cancel, which emptied go_router and threw. It is now pushed by the app shell, whose mounting is exactly the precondition - the router only builds it for a signed-in user with a study - so a pop always has somewhere to land. Drops the cached tri-state consent status, the consent listener that configured the study as a side effect, and the redirect rule. The view model now owns the local flag and the accept / reject decision; the service is left as a pure CAWS connector.
The app bar pushed the profile imperatively onto the root navigator with its own PageRoute, bypassing the router and building a throwaway view model instead of the shared one. Route to it instead, moved out of the shell since profile is not a bottom-nav tab.
Introduces lib/core (bloc, sensing, CAWS backend, resource managers) and lib/helpers (config, logging, utils), retiring lib/blocs. View model files are renamed to *_view_model.dart and each documents, in the same shape, which page it backs, the state it holds, and its responsibility. Drops logAppState and its state snapshot, which dumped seventeen lines on every router redirect, along with the temporary timing logs.
Names the page and its view model after the tab the user actually sees - StatisticsPage and StatisticsViewModel - matching the naming used everywhere else. The /data route is unchanged.
Adds a 14-day task completion chart and turns the task and survey rings into donuts, each section gated on data the study actually has: app tasks, two or more survey types, or the matching measure in the protocol. Drops the media and mobility cards. Every chart now selects the same way - the selected bar or slice stays solid, the rest fade, and the figures above the chart follow it. Several had a BarTouchData that was disabled, so their touch callbacks never ran, and an inverted alpha that lightened the selected bar instead. Also fixes the survey donut's centre, which counted survey types rather than completed surveys.
The placeholder data was pre-aggregated maps, so it proved nothing about the live path. It is now StepCount, PolarHR and Activity measurements stamped with the time they were taken, folded by the same code that folds readings off the sampling streams - connecting the real streams changes where the data comes from and nothing about how it is read. That aggregation now buckets by each measurement's own timestamp instead of DateTime.now(), which is also what makes replaying history possible. Demo data is off on a production deployment, derived from the deployment mode rather than a flag someone can leave switched on.
Move the message type into a pill above the title so a long title no longer collides with it, and rebuild the page in the design 2.0 card style.
Replace the type stripe with a tinted badge, collapse the three card builders into one shell, and swap the pinned tab header for a segmented control - its extent could not match TabBar.preferredSize, which broke the sliver geometry. Filtering moves to the view model so each tab builds only its own rows and can show a count and its own empty state.
Title the page Connections to match the nav bar, drop the uppercase section headings, and align every inset to 16. Device icons move into the tinted badge the task and feed cards use, and the FittedBox scale-down wrappers give way to wrapping text so titles keep a consistent size.
The selected bar could not be unselected, so the fortnight total was never shown. Selection is now nullable and clears on a second tap, on empty chart space, or on a tap elsewhere on the card. The title follows the selection - the fortnight, or the day tapped.
… study_about rename) + theme package integration
…ress review comments
Declining consent - or leaving the study any other way - left the background sensing foreground service running with nothing to sense. leaveStudy() now disconnects it before removing the deployment.
…t target research_package 3.2.0 no longer pops the task's route when it is the only one in the stack, so the closeAfterFinished opt-out is not needed. New test declines the consent - the case that crashed go_router with 'currentConfiguration.isNotEmpty'. rootBundle is cleared per test: a translation Future cached from another test's FakeAsync zone never completes, leaving Localizations - and the page - unbuilt.
…YES/NO One _confirm helper: the action is the title and the red confirm button - Cancel | Leave study - and the dialog closes before the work runs, instead of freezing open across the network round trip.
Tapping download wrote the consent into the app's private documents directory and reported 'Informed consent saved.' - a directory no file browser on either platform can reach, so nothing was downloaded. The file now goes to the system share sheet, which is what lets the participant keep it: Save to Files, mail, Drive. The success snackbar goes with it - the sheet is its own feedback, and it can be dismissed. Fetching moves to ConsentService, which already owns backend consent access with an injectable backend; the view model had a second, untestable copy.
The share sheet asks who to send the file to; the ask was to download it. It now writes straight to a folder the participant can browse - Downloads on Android, the app's folder in Files on iOS (UIFileSharingEnabled is already set) - and the snackbar names where it went.
…ndling fix(consent): show consent once, and recover from a failed upload
feat(sensing): let the user turn on background sensing
feat(sensing): background sensing on iOS via the Always location permission
fix: download the signed informed consent as a PDF (#678)
Location updates are what keep sampling alive - the same anchor iOS uses - so the already-approved FOREGROUND_SERVICE_LOCATION covers the service. Drops the specialUse permission, its manual Play review, and the manual console upload it forced, with no 6h/day cap.
We only open a PDF written to our own cache, never gallery media, so the READ_MEDIA_* permissions are unused - and keeping them makes Play demand a photo and video access declaration.
fix(android): drop the media permissions open_filex pulls in
The photo preview handed a JPEG to the video player, and the background sensing service asked only for the battery exemption while Android 14+ also requires location for a location-type foreground service.
askForPermissions: Platform.isAndroid was a no-op - CAMS' askForAllPermissions() already returns early on iOS, so the flag only duplicated a guard the framework has. Use the default (true) and let CAMS decide per platform.
fix: photo preview, Android background sensing and iOS permission guidance
fix: permission startup handling for 5.0.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.