diff --git a/Hydroflux/app/src/main/assets/js/modules/dashboard.js b/Hydroflux/app/src/main/assets/js/modules/dashboard.js index 24362fd..cb6d5b5 100644 --- a/Hydroflux/app/src/main/assets/js/modules/dashboard.js +++ b/Hydroflux/app/src/main/assets/js/modules/dashboard.js @@ -145,15 +145,15 @@ export class Dashboard { - +
-

Strava Integration

+

Distance

- S + D
- 5.2km Run - Last Sync: 2h ago + ${(healthData.distance || 0).toFixed(2)}km + Today's Total
@@ -195,11 +195,15 @@ export class Dashboard { this.renderGoals(goalsData); // Expose Native Callback - window.updateHealthData = (steps, sleepHoursTotal) => { - console.log("Received Health Data:", steps, sleepHoursTotal); + window.updateHealthData = (steps, sleepHoursTotal, distanceKm) => { + console.log("Received Health Data:", steps, sleepHoursTotal, distanceKm); // Save to Storage - localStorage.setItem('hydroflux_health_data', JSON.stringify({ steps: steps, sleep: sleepHoursTotal })); + localStorage.setItem('hydroflux_health_data', JSON.stringify({ + steps: steps, + sleep: sleepHoursTotal, + distance: distanceKm || 0 // Default to 0 if undefined + })); // Update UI directly const stepsCount = this.container.querySelector('#stepsCount'); @@ -210,7 +214,21 @@ export class Dashboard { const sleepTime = this.container.querySelector('#sleepTime'); if (sleepTime) sleepTime.textContent = `${sh}h ${sm}m`; + // Update Distance Card (Replacing Strava Placeholder or updating it) + // Assuming the Strava card is now the general Fitness/Distance card as requested? + // "can we have the distance tab actually pull stats from health connect" + // Let's look for a distance element or update the text '5.2km Run' -> 'X.X km' + + // NOTE: The current HTML has "5.2km Run" hardcoded in the Strava card. + // I should verify if I should target that specific element. + // There is no ID on that span. I'll add one via full replacement of render or just target via text? + // Safer to re-render or target widely. + + // Let's assume I upgrade the render() to include an ID first? + // Actually, let's just save the data here. The Dashboard.render() needs to read it. + this.updateDynamicElements(steps, 10000); + if (this.updateDistanceDisplay) this.updateDistanceDisplay(distanceKm); }; // Trigger initial sync if native interface exists @@ -395,6 +413,11 @@ export class Dashboard { } } + updateDistanceDisplay(distance) { + const el = this.container.querySelector('#distanceDisplay'); + if (el) el.textContent = (distance || 0).toFixed(2) + 'km'; + } + startTimers() { const updateTime = () => { const now = new Date(); diff --git a/Hydroflux/app/src/main/java/com/david/hydroflux/MainActivity.kt b/Hydroflux/app/src/main/java/com/david/hydroflux/MainActivity.kt index ff7e8ad..2e02eb5 100644 --- a/Hydroflux/app/src/main/java/com/david/hydroflux/MainActivity.kt +++ b/Hydroflux/app/src/main/java/com/david/hydroflux/MainActivity.kt @@ -13,6 +13,7 @@ import androidx.health.connect.client.HealthConnectClient import androidx.health.connect.client.permission.HealthPermission import androidx.health.connect.client.records.StepsRecord import androidx.health.connect.client.records.SleepSessionRecord +import androidx.health.connect.client.records.DistanceRecord // Added import androidx.health.connect.client.request.ReadRecordsRequest import androidx.health.connect.client.request.AggregateRequest import androidx.health.connect.client.time.TimeRangeFilter @@ -28,7 +29,8 @@ class MainActivity : FragmentActivity() { // Define Permissions we need private val PERMISSIONS = setOf( HealthPermission.getReadPermission(StepsRecord::class), - HealthPermission.getReadPermission(SleepSessionRecord::class) + HealthPermission.getReadPermission(SleepSessionRecord::class), + HealthPermission.getReadPermission(DistanceRecord::class) // Added ) private val requestPermissions = registerForActivityResult( @@ -169,55 +171,74 @@ class MainActivity : FragmentActivity() { val startOfDay = ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS).toInstant() val now = Instant.now() - var totalSteps = 0L - var sleepHours = 0.0 - - // 1. Try Read Steps (AGGREGATE) - try { - val response = healthConnectClient.aggregate( - AggregateRequest( - metrics = setOf(StepsRecord.COUNT_TOTAL), - timeRangeFilter = TimeRangeFilter.between(startOfDay, now) - ) + var totalSteps = 0L + var sleepHours = 0.0 + var totalDistance = 0.0 + + // 1. Try Read Steps (AGGREGATE) + try { + val response = healthConnectClient.aggregate( + AggregateRequest( + metrics = setOf(StepsRecord.COUNT_TOTAL), + timeRangeFilter = TimeRangeFilter.between(startOfDay, now) ) - // The result may be null if no data - totalSteps = response[StepsRecord.COUNT_TOTAL] ?: 0 - } catch (e: Exception) { - e.printStackTrace() - val msg = e.message ?: "Unknown Error" - runOnUiThread { Toast.makeText(activity, "Steps Error: $msg", Toast.LENGTH_LONG).show() } - totalSteps = 0 - } - - // 2. Try Read Sleep (AGGREGATE) - try { - val sleepResponse = healthConnectClient.aggregate( - AggregateRequest( - metrics = setOf(SleepSessionRecord.SLEEP_DURATION_TOTAL), - timeRangeFilter = TimeRangeFilter.between(now.minus(24, ChronoUnit.HOURS), now) - ) + ) + // The result may be null if no data + totalSteps = response[StepsRecord.COUNT_TOTAL] ?: 0 + } catch (e: Exception) { + e.printStackTrace() + val msg = e.message ?: "Unknown Error" + runOnUiThread { Toast.makeText(activity, "Steps Error: $msg", Toast.LENGTH_LONG).show() } + totalSteps = 0 + } + + // 2. Try Read Sleep (AGGREGATE) + try { + val sleepResponse = healthConnectClient.aggregate( + AggregateRequest( + metrics = setOf(SleepSessionRecord.SLEEP_DURATION_TOTAL), + timeRangeFilter = TimeRangeFilter.between(now.minus(24, ChronoUnit.HOURS), now) ) - // Get total duration in Seconds (Duration -> Seconds) - val duration = sleepResponse[SleepSessionRecord.SLEEP_DURATION_TOTAL] - if (duration != null) { - sleepHours = duration.seconds / 3600.0 - } - } catch (e: Exception) { - e.printStackTrace() - sleepHours = 0.0 + ) + // Get total duration in Seconds (Duration -> Seconds) + val duration = sleepResponse[SleepSessionRecord.SLEEP_DURATION_TOTAL] + if (duration != null) { + sleepHours = duration.seconds / 3600.0 } - - runOnUiThread { - if (!activity.isFinishing && !activity.isDestroyed) { - try { - myWebView.evaluateJavascript("window.updateHealthData($totalSteps, $sleepHours)", null) - } catch (e: Exception) { - e.printStackTrace() - } + } catch (e: Exception) { + e.printStackTrace() + sleepHours = 0.0 + } + + // 3. Try Read Distance (AGGREGATE) + try { + val distanceResponse = healthConnectClient.aggregate( + AggregateRequest( + metrics = setOf(DistanceRecord.DISTANCE_TOTAL), + timeRangeFilter = TimeRangeFilter.between(startOfDay, now) + ) + ) + val dist = distanceResponse[DistanceRecord.DISTANCE_TOTAL] + if (dist != null) { + totalDistance = dist.inKilometers // Double + } + } catch (e: Exception) { + e.printStackTrace() + totalDistance = 0.0 + } + + runOnUiThread { + if (!activity.isFinishing && !activity.isDestroyed) { + try { + // Pass Steps, Sleep, AND Distance + myWebView.evaluateJavascript("window.updateHealthData($totalSteps, $sleepHours, $totalDistance)", null) + } catch (e: Exception) { + e.printStackTrace() } } } } + } } } diff --git a/Hydroflux/releases/HydroFlux V7.apk b/Hydroflux/releases/HydroFlux V7.apk new file mode 100644 index 0000000..a6fcd21 Binary files /dev/null and b/Hydroflux/releases/HydroFlux V7.apk differ