|
|
|
import 'package:doublefeel_flutter/core/network/api/friend_api.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
|
|
|
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
|
|
|
|
import 'package:doublefeel_flutter/data/models/friend/friend_models.dart'
|
|
|
|
as api_models;
|
|
|
|
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
import 'package:intl/intl.dart';
|
|
|
|
|
|
|
|
import '../models/friend_health_data.dart';
|
|
...
|
...
|
@@ -34,9 +36,10 @@ class FriendListData { |
|
|
|
}
|
|
|
|
|
|
|
|
class FriendsRepositoryImpl implements FriendsRepository {
|
|
|
|
const FriendsRepositoryImpl(this._friendApi);
|
|
|
|
const FriendsRepositoryImpl(this._friendApi, [this._userPreferencesStorage]);
|
|
|
|
|
|
|
|
final FriendApi _friendApi;
|
|
|
|
final UserPreferencesStorage? _userPreferencesStorage;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<List<FriendHealthData>> getFriends(
|
|
...
|
...
|
@@ -96,6 +99,7 @@ class FriendsRepositoryImpl implements FriendsRepository { |
|
|
|
final healthData = friend.healthData;
|
|
|
|
final nickname = friend.friendNickname?.trim();
|
|
|
|
final remark = friend.remarkName?.trim();
|
|
|
|
final stressData = _stressData(healthData);
|
|
|
|
|
|
|
|
return FriendHealthData(
|
|
|
|
friendItem: friend,
|
|
...
|
...
|
@@ -105,13 +109,13 @@ class FriendsRepositoryImpl implements FriendsRepository { |
|
|
|
? l10n.friendsUnknownFriend
|
|
|
|
: nickname,
|
|
|
|
remark: remark == null || remark.isEmpty ? null : remark,
|
|
|
|
updatedAt: _updatedAt(healthData?.lastDataTime ?? friend.updateTime),
|
|
|
|
updatedAt: _updatedAt(stressData.updatedAt),
|
|
|
|
sleepQualityScore: healthData?.sleepEvaluate,
|
|
|
|
steps: healthData?.totalSteps == null
|
|
|
|
? null
|
|
|
|
: l10n.friendsStepCount(healthData!.totalSteps!),
|
|
|
|
stressState:
|
|
|
|
FriendStressState.fromValue(healthData?.comprehensiveStressState),
|
|
|
|
stressState: stressData.state,
|
|
|
|
stressValueText: stressData.valueText,
|
|
|
|
isOnWatchFace: friend.isShowInDial,
|
|
|
|
);
|
|
|
|
}
|
|
...
|
...
|
@@ -120,22 +124,85 @@ class FriendsRepositoryImpl implements FriendsRepository { |
|
|
|
api_models.FriendHealthData? healthData,
|
|
|
|
) {
|
|
|
|
if (healthData == null) return null;
|
|
|
|
final stressData = _stressData(healthData);
|
|
|
|
return SelfFriendHealthData(
|
|
|
|
updatedAt: _updatedAt(healthData.lastDataTime),
|
|
|
|
updatedAt: _updatedAt(stressData.updatedAt),
|
|
|
|
sleepQualityScore: healthData.sleepEvaluate,
|
|
|
|
steps: healthData.totalSteps == null
|
|
|
|
? null
|
|
|
|
: l10n.friendsStepCount(healthData.totalSteps!),
|
|
|
|
stressState:
|
|
|
|
FriendStressState.fromValue(healthData.comprehensiveStressState),
|
|
|
|
stressState: stressData.state,
|
|
|
|
stressValueText: stressData.valueText,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
_FriendStressData _stressData(api_models.FriendHealthData? healthData) {
|
|
|
|
if (healthData == null) return const _FriendStressData();
|
|
|
|
|
|
|
|
if (_showRealtimeStress) {
|
|
|
|
final realtime = _latestRealtimeStress(healthData.realtimeStress);
|
|
|
|
return _FriendStressData(
|
|
|
|
state: FriendStressState.fromValue(realtime?.state),
|
|
|
|
valueText: _valueText(realtime?.value, '%'),
|
|
|
|
updatedAt: realtime?.time,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _FriendStressData(
|
|
|
|
state: FriendStressState.fromValue(healthData.hrvState),
|
|
|
|
valueText: _valueText(healthData.latestHrv, 'ms'),
|
|
|
|
updatedAt: healthData.lastDataTime,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool get _showRealtimeStress {
|
|
|
|
final preferences =
|
|
|
|
(_userPreferencesStorage ?? Get.find<UserPreferencesStorage>())
|
|
|
|
.preferences
|
|
|
|
.value;
|
|
|
|
return preferences.vipInfo?.isVip == true &&
|
|
|
|
(preferences.showRealtimeStress ?? true);
|
|
|
|
}
|
|
|
|
|
|
|
|
api_models.FriendRealtimeStressItem? _latestRealtimeStress(
|
|
|
|
List<api_models.FriendRealtimeStressItem>? samples,
|
|
|
|
) {
|
|
|
|
if (samples == null || samples.isEmpty) return null;
|
|
|
|
return samples.reduce(
|
|
|
|
(latest, sample) => (sample.time ?? -1) > (latest.time ?? -1)
|
|
|
|
? sample
|
|
|
|
: latest,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
String? _valueText(double? value, String unit) {
|
|
|
|
if (value == null) return null;
|
|
|
|
final text = value == value.truncateToDouble()
|
|
|
|
? value.toInt().toString()
|
|
|
|
: value.toString();
|
|
|
|
return '$text$unit';
|
|
|
|
}
|
|
|
|
|
|
|
|
String _updatedAt(num? timestamp) {
|
|
|
|
if (timestamp == null) return l10n.friendsWaitingForData;
|
|
|
|
final milliseconds =
|
|
|
|
timestamp < 1000000000000 ? timestamp * 1000 : timestamp;
|
|
|
|
final time = DateTime.fromMillisecondsSinceEpoch(milliseconds.toInt());
|
|
|
|
return l10n.friendsUpdatedAt(DateFormat('HH:mm').format(time));
|
|
|
|
final formattedTime = DateFormat('HH:mm').format(time);
|
|
|
|
return _showRealtimeStress
|
|
|
|
? l10n.friendsRealtimeStressUpdatedAt(formattedTime)
|
|
|
|
: l10n.friendsHrvUpdatedAt(formattedTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _FriendStressData {
|
|
|
|
const _FriendStressData({
|
|
|
|
this.state = FriendStressState.wait,
|
|
|
|
this.valueText,
|
|
|
|
this.updatedAt,
|
|
|
|
});
|
|
|
|
|
|
|
|
final FriendStressState state;
|
|
|
|
final String? valueText;
|
|
|
|
final num? updatedAt;
|
|
|
|
} |
...
|
...
|
|