Commit 20896cf52d84967e6ccc5af87f10fbfa1d198806

Authored by 刘宏哲
1 parent 83c0f089

feat(app): add health datasource

import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource_wrapper.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_local_datasource.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_remote_datasource.dart';
import 'package:get/get.dart';
import '../../report_common/controllers/report_period_logic.dart';
... ... @@ -14,7 +18,7 @@ class ActivityBurnReportLogic extends ReportPeriodLogic {
}) : repository = repository ??
ActivityBurnReportRepositoryImpl(
dataSource:
ApiActivityBurnReportDataSource(Get.find<HealthApi>()),
ApiActivityBurnReportDataSource(_healthDataSource()),
) {
targetUserId.value = initialTargetUserId;
}
... ... @@ -23,6 +27,11 @@ class ActivityBurnReportLogic extends ReportPeriodLogic {
final ActivityBurnReportRepository repository;
static HealthDataSource _healthDataSource() => HealthDataSourceWrapper(
remoteDataSource: RemoteHealthDataSource(Get.find<HealthApi>()),
localDataSource: const LocalHealthDataSource(),
);
final report = Rxn<ActivityBurnReport>();
final weeklyReport = Rxn<WeeklyActivityBurnReport>();
final monthlyReport = Rxn<MonthlyActivityBurnReport>();
... ...
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource.dart';
import 'package:doublefeel_flutter/data/models/health/activity/activity_burn_statistics_data_v2.dart';
import '../models/activity_burn_report_models.dart';
... ... @@ -22,13 +22,13 @@ abstract class ActivityBurnReportDataSource {
}
class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
const ApiActivityBurnReportDataSource(this._healthApi);
const ApiActivityBurnReportDataSource(this._healthDataSource);
static const _weekDateRangeType = 0;
static const _monthDateRangeType = 1;
static const _dayDateRangeType = 3;
final HealthApi _healthApi;
final HealthDataSource _healthDataSource;
@override
Future<ActivityBurnReport> fetchDailyReport(
... ... @@ -36,7 +36,7 @@ class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
int? targetUserId,
}) async {
final day = _normalizeDate(date);
final result = await _healthApi.getActivityBurnStatistics(
final result = await _healthDataSource.getActivityBurnStatistics(
_dayDateRangeType,
_dateKey(day),
queryUserId: targetUserId,
... ... @@ -53,7 +53,7 @@ class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
int? targetUserId,
}) async {
final start = _normalizeDate(weekStart);
final result = await _healthApi.getActivityBurnStatistics(
final result = await _healthDataSource.getActivityBurnStatistics(
_weekDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ... @@ -81,7 +81,7 @@ class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
}) async {
final start = DateTime(monthStart.year, monthStart.month);
final end = DateTime(start.year, start.month + 1, 0);
final result = await _healthApi.getActivityBurnStatistics(
final result = await _healthDataSource.getActivityBurnStatistics(
_monthDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ... @@ -317,4 +317,4 @@ class _SleepRange {
final DateTime start;
final DateTime end;
}
\ No newline at end of file
}
... ...
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource_wrapper.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_local_datasource.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_remote_datasource.dart';
import 'package:get/get.dart';
import '../../report_common/controllers/report_period_logic.dart';
... ... @@ -13,7 +17,7 @@ class HrvReportLogic extends ReportPeriodLogic {
HrvReportRepository? repository,
}) : repository = repository ??
HrvReportRepositoryImpl(
dataSource: ApiHrvReportDataSource(Get.find<HealthApi>()),
dataSource: ApiHrvReportDataSource(_healthDataSource()),
) {
targetUserId.value = initialTargetUserId;
selectedPeriod.value = ReportPeriod.week;
... ... @@ -25,6 +29,11 @@ class HrvReportLogic extends ReportPeriodLogic {
final yearlyReport = Rxn<YearlyHrvReport>();
final HrvReportRepository repository;
static HealthDataSource _healthDataSource() => HealthDataSourceWrapper(
remoteDataSource: RemoteHealthDataSource(Get.find<HealthApi>()),
localDataSource: const LocalHealthDataSource(),
);
@override
List<ReportPeriod> get supportedPeriods => const [
ReportPeriod.week,
... ...
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource.dart';
import 'package:doublefeel_flutter/data/models/health/hrv/hrv_statistics_data.dart';
import '../models/hrv_report_models.dart';
... ... @@ -22,13 +22,13 @@ abstract class HrvReportDataSource {
}
class ApiHrvReportDataSource implements HrvReportDataSource {
const ApiHrvReportDataSource(this._healthApi);
const ApiHrvReportDataSource(this._healthDataSource);
static const _weekDateRangeType = 0;
static const _monthDateRangeType = 1;
static const _yearDateRangeType = 2;
final HealthApi _healthApi;
final HealthDataSource _healthDataSource;
@override
Future<WeeklyHrvReport> fetchWeeklyReport(
... ... @@ -36,7 +36,7 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
int? targetUserId,
}) async {
final start = DateTime(weekStart.year, weekStart.month, weekStart.day);
final result = await _healthApi.getHrvStatistics(
final result = await _healthDataSource.getHrvStatistics(
_weekDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ... @@ -53,7 +53,7 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
int? targetUserId,
}) async {
final start = DateTime(monthStart.year, monthStart.month);
final result = await _healthApi.getHrvStatistics(
final result = await _healthDataSource.getHrvStatistics(
_monthDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ... @@ -70,7 +70,7 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
int? targetUserId,
}) async {
final start = DateTime(year);
final result = await _healthApi.getHrvStatistics(
final result = await _healthDataSource.getHrvStatistics(
_yearDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ...
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource_wrapper.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_local_datasource.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_remote_datasource.dart';
import 'package:get/get.dart';
import '../../report_common/controllers/report_period_logic.dart';
... ... @@ -13,7 +17,7 @@ class SleepReportLogic extends ReportPeriodLogic {
SleepReportRepository? repository,
}) : repository = repository ??
SleepReportRepositoryImpl(
dataSource: ApiSleepReportDataSource(Get.find<HealthApi>()),
dataSource: ApiSleepReportDataSource(_healthDataSource()),
) {
targetUserId.value = initialTargetUserId;
}
... ... @@ -22,6 +26,11 @@ class SleepReportLogic extends ReportPeriodLogic {
final SleepReportRepository repository;
static HealthDataSource _healthDataSource() => HealthDataSourceWrapper(
remoteDataSource: RemoteHealthDataSource(Get.find<HealthApi>()),
localDataSource: const LocalHealthDataSource(),
);
final report = Rxn<SleepReport>();
final weeklyReport = Rxn<WeeklySleepReport>();
final monthlyReport = Rxn<MonthlySleepReport>();
... ...
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_datasource.dart';
import 'package:doublefeel_flutter/data/models/health/sleep/sleep_statistics_data.dart';
import '../models/sleep_report_models.dart';
... ... @@ -22,13 +22,13 @@ abstract class SleepReportDataSource {
}
class ApiSleepReportDataSource implements SleepReportDataSource {
const ApiSleepReportDataSource(this._healthApi);
const ApiSleepReportDataSource(this._healthDataSource);
static const _weekDateRangeType = 0;
static const _monthDateRangeType = 1;
static const _dayDateRangeType = 3;
final HealthApi _healthApi;
final HealthDataSource _healthDataSource;
@override
Future<SleepReport> fetchDailyReport(
... ... @@ -36,7 +36,7 @@ class ApiSleepReportDataSource implements SleepReportDataSource {
int? targetUserId,
}) async {
final day = _normalizeDate(date);
final result = await _healthApi.getSleepStatistics(
final result = await _healthDataSource.getSleepStatistics(
_dayDateRangeType,
_dateKey(day),
queryUserId: targetUserId,
... ... @@ -53,7 +53,7 @@ class ApiSleepReportDataSource implements SleepReportDataSource {
int? targetUserId,
}) async {
final start = _normalizeDate(weekStart);
final result = await _healthApi.getSleepStatistics(
final result = await _healthDataSource.getSleepStatistics(
_weekDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ... @@ -70,7 +70,7 @@ class ApiSleepReportDataSource implements SleepReportDataSource {
int? targetUserId,
}) async {
final start = DateTime(monthStart.year, monthStart.month);
final result = await _healthApi.getSleepStatistics(
final result = await _healthDataSource.getSleepStatistics(
_monthDateRangeType,
_dateKey(start),
queryUserId: targetUserId,
... ...
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/models/health/activity/activity_burn_statistics_data_v2.dart';
import 'package:doublefeel_flutter/data/models/health/hrv/hrv_statistics_data.dart';
import 'package:doublefeel_flutter/data/models/health/sleep/sleep_statistics_data.dart';
/// Data access contract shared by health features.
abstract interface class HealthDataSource {
Future<AppResult<SleepStatisticsData>> getSleepStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
});
Future<AppResult<ActivityBurnStatisticsDataV2>> getActivityBurnStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
});
Future<AppResult<HrvStatisticsDataV2>> getHrvStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
});
}
... ...
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/models/health/activity/activity_burn_statistics_data_v2.dart';
import 'package:doublefeel_flutter/data/models/health/hrv/hrv_statistics_data.dart';
import 'package:doublefeel_flutter/data/models/health/sleep/sleep_statistics_data.dart';
import 'health_datasource.dart';
/// Routes each report type to its current source of truth.
class HealthDataSourceWrapper implements HealthDataSource {
const HealthDataSourceWrapper({
required this.remoteDataSource,
required this.localDataSource,
});
final HealthDataSource remoteDataSource;
final HealthDataSource localDataSource;
@override
Future<AppResult<SleepStatisticsData>> getSleepStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) {
return remoteDataSource.getSleepStatistics(
dateRangeType,
startDate,
queryUserId: queryUserId,
);
}
@override
Future<AppResult<ActivityBurnStatisticsDataV2>> getActivityBurnStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) {
return localDataSource.getActivityBurnStatistics(
dateRangeType,
startDate,
queryUserId: queryUserId,
);
}
@override
Future<AppResult<HrvStatisticsDataV2>> getHrvStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) {
return localDataSource.getHrvStatistics(
dateRangeType,
startDate,
queryUserId: queryUserId,
);
}
}
... ...
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/models/health/activity/activity_burn_statistics_data_v2.dart';
import 'package:doublefeel_flutter/data/models/health/hrv/hrv_statistics_data.dart';
import 'package:doublefeel_flutter/data/models/health/sleep/sleep_statistics_data.dart';
import 'health_datasource.dart';
/// Placeholder for the local health-data store.
class LocalHealthDataSource implements HealthDataSource {
const LocalHealthDataSource();
Never _notImplemented() => throw UnimplementedError(
'Local health data source has not been implemented.',
);
@override
Future<AppResult<SleepStatisticsData>> getSleepStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) =>
_notImplemented();
@override
Future<AppResult<ActivityBurnStatisticsDataV2>> getActivityBurnStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) =>
_notImplemented();
@override
Future<AppResult<HrvStatisticsDataV2>> getHrvStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) =>
_notImplemented();
}
... ...
import 'package:doublefeel_flutter/core/network/api/health_api.dart';
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/models/health/activity/activity_burn_statistics_data_v2.dart';
import 'package:doublefeel_flutter/data/models/health/hrv/hrv_statistics_data.dart';
import 'package:doublefeel_flutter/data/models/health/sleep/sleep_statistics_data.dart';
import 'health_datasource.dart';
/// Remote implementation backed by the health API.
class RemoteHealthDataSource implements HealthDataSource {
const RemoteHealthDataSource(this._healthApi);
final HealthApi _healthApi;
@override
Future<AppResult<SleepStatisticsData>> getSleepStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) {
return _healthApi.getSleepStatistics(
dateRangeType,
startDate,
queryUserId: queryUserId,
);
}
@override
Future<AppResult<ActivityBurnStatisticsDataV2>> getActivityBurnStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) {
return _healthApi.getActivityBurnStatistics(
dateRangeType,
startDate,
queryUserId: queryUserId,
);
}
@override
Future<AppResult<HrvStatisticsDataV2>> getHrvStatistics(
int dateRangeType,
int startDate, {
int? queryUserId,
}) {
return _healthApi.getHrvStatistics(
dateRangeType,
startDate,
queryUserId: queryUserId,
);
}
}
... ...