|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:doublefeel_flutter/core/logging/app_logger.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/network/api/harmony_api.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/network/dio_client.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/platform/pigeon_api_facade.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
|
|
|
import 'package:doublefeel_flutter/data/models/harmony/hm_health_data.dart';
|
|
...
|
...
|
@@ -31,15 +35,37 @@ OhosHealthRawDataSyncService createDefaultOhosHealthRawDataSyncService({ |
|
|
|
return OhosHealthRawDataSyncService(
|
|
|
|
localStore: localStore,
|
|
|
|
remoteDataSource: OhosHarmonyHealthRawDataRemoteDataSource(
|
|
|
|
HarmonyApiOhosRawDataClient(Get.find<HarmonyApi>()),
|
|
|
|
HarmonyApiOhosRawDataClient(
|
|
|
|
Get.find<HarmonyApi>(),
|
|
|
|
healthApi: _resolveHealthApi(),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// HealthApi is normally lazy-registered. Activity-goal synchronization can
|
|
|
|
/// start before that lazy dependency is materialized, so construct the same
|
|
|
|
/// lightweight API wrapper from the app-wide DioClient as a fallback.
|
|
|
|
HealthApi? _resolveHealthApi() {
|
|
|
|
if (Get.isRegistered<HealthApi>()) {
|
|
|
|
return Get.find<HealthApi>();
|
|
|
|
}
|
|
|
|
if (Get.isRegistered<DioClient>()) {
|
|
|
|
return HealthApi(Get.find<DioClient>());
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
class HarmonyApiOhosRawDataClient implements OhosHarmonyRawDataClient {
|
|
|
|
const HarmonyApiOhosRawDataClient(this._harmonyApi, [this._healthKitApi]);
|
|
|
|
const HarmonyApiOhosRawDataClient(
|
|
|
|
this._harmonyApi, {
|
|
|
|
HealthApi? healthApi,
|
|
|
|
AppHealthKitHostApi? healthKitApi,
|
|
|
|
}) : _healthApi = healthApi,
|
|
|
|
_healthKitApi = healthKitApi;
|
|
|
|
|
|
|
|
final HarmonyApi _harmonyApi;
|
|
|
|
final HealthApi? _healthApi;
|
|
|
|
final AppHealthKitHostApi? _healthKitApi;
|
|
|
|
|
|
|
|
bool get _preferNativeHealthData =>
|
|
...
|
...
|
@@ -118,11 +144,6 @@ class HarmonyApiOhosRawDataClient implements OhosHarmonyRawDataClient { |
|
|
|
|
|
|
|
@override
|
|
|
|
Future<AppResult<V2ActivityTarget>> getActivityGoal() async {
|
|
|
|
if (!_preferNativeHealthData) {
|
|
|
|
AppLogger.i('[OHOS_ACTIVITY_GOAL] source=remote native_enabled=false');
|
|
|
|
return _harmonyApi.getActivityGoal();
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
final goal =
|
|
|
|
await (_healthKitApi ?? AppHealthKitHostApi()).readActivityGoal();
|
|
...
|
...
|
@@ -138,6 +159,13 @@ class HarmonyApiOhosRawDataClient implements OhosHarmonyRawDataClient { |
|
|
|
'[OHOS_ACTIVITY_GOAL] '
|
|
|
|
'source=native value=${_goalLogValue(nativeGoal)}',
|
|
|
|
);
|
|
|
|
AppLogger.i(
|
|
|
|
'[OHOS_ACTIVITY_GOAL] '
|
|
|
|
'upload_scheduled value=${_goalLogValue(nativeGoal)}',
|
|
|
|
);
|
|
|
|
// Deliberately do not await: a failed request must not prevent the
|
|
|
|
// user from entering the app or the health-data sync from continuing.
|
|
|
|
unawaited(_uploadNativeActivityGoal(nativeGoal));
|
|
|
|
return AppSuccess(nativeGoal);
|
|
|
|
}
|
|
|
|
}
|
|
...
|
...
|
@@ -163,6 +191,29 @@ class HarmonyApiOhosRawDataClient implements OhosHarmonyRawDataClient { |
|
|
|
return remoteResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _uploadNativeActivityGoal(V2ActivityTarget goal) async {
|
|
|
|
final healthApi = _healthApi;
|
|
|
|
if (healthApi == null) {
|
|
|
|
AppLogger.i(
|
|
|
|
'[OHOS_ACTIVITY_GOAL] upload_skipped reason=health_api_missing');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final result = await healthApi.uploadV2ActivityTarget(goal);
|
|
|
|
switch (result) {
|
|
|
|
case AppSuccess():
|
|
|
|
AppLogger.i(
|
|
|
|
'[OHOS_ACTIVITY_GOAL] '
|
|
|
|
'upload_success value=${_goalLogValue(goal)}',
|
|
|
|
);
|
|
|
|
case AppFailure(:final error):
|
|
|
|
AppLogger.i(
|
|
|
|
'[OHOS_ACTIVITY_GOAL] '
|
|
|
|
'upload_failed error=$error value=${_goalLogValue(goal)}',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool _hasGoal(V2ActivityTarget goal) {
|
|
|
|
return goal.move != null ||
|
|
|
|
goal.step != null ||
|
...
|
...
|
|