feat(watch): clôture lot #91 - fréquence cardiaque live, notifications de séance et finitions montre

Consolide le lot applicatif watch companion validé :
- télémétrie fréquence cardiaque live remontée montre -> téléphone
  (collecteur watch, adapter Wear Data Layer, persistance Drift,
  propagation aux écrans historique/programme/profil/exécution)
- notifications de séance en arrière-plan côté téléphone (service
  foreground de statut + passerelle applicative)
- finitions montre : chrono d'étape, score d'étape, retrait du bouton
  "lancer une séance", thème, icônes et polices watch_app

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 05:56:12 +02:00
parent c65a5a76a9
commit 65d43b9768
80 changed files with 12292 additions and 892 deletions

View File

@ -16,6 +16,10 @@ final class WatchBridgeConnectionEvent {
abstract interface class WatchBridgeNativeChannel {
Stream<WatchCommandEnvelope> get commands;
Stream<WatchSensorSummary> get sensorSummaries;
Stream<WatchSensorSample> get sensorSamples;
Stream<WatchBridgeConnectionEvent> get connectionEvents;
Future<void> publishProjection(WatchSessionProjection projection);
@ -38,17 +42,31 @@ final class MethodChannelWatchBridgeNativeChannel
const MethodChannelWatchBridgeNativeChannel({
MethodChannel methodChannel = const MethodChannel(_methodChannelName),
EventChannel commandChannel = const EventChannel(_commandChannelName),
EventChannel sensorSummaryChannel = const EventChannel(
_sensorSummaryChannelName,
),
EventChannel sensorSampleChannel = const EventChannel(
_sensorSampleChannelName,
),
EventChannel connectionChannel = const EventChannel(_connectionChannelName),
}) : _methodChannel = methodChannel,
_commandChannel = commandChannel,
_sensorSummaryChannel = sensorSummaryChannel,
_sensorSampleChannel = sensorSampleChannel,
_connectionChannel = connectionChannel;
static const _methodChannelName = 'gametime.watch_bridge/methods';
static const _commandChannelName = 'gametime.watch_bridge/commands';
static const _sensorSummaryChannelName =
'gametime.watch_bridge/sensor_summaries';
static const _sensorSampleChannelName =
'gametime.watch_bridge/sensor_samples';
static const _connectionChannelName = 'gametime.watch_bridge/connection';
final MethodChannel _methodChannel;
final EventChannel _commandChannel;
final EventChannel _sensorSummaryChannel;
final EventChannel _sensorSampleChannel;
final EventChannel _connectionChannel;
@override
@ -63,6 +81,30 @@ final class MethodChannelWatchBridgeNativeChannel
});
}
@override
Stream<WatchSensorSummary> get sensorSummaries {
return _sensorSummaryChannel
.receiveBroadcastStream()
.where((event) {
return event is Map;
})
.map((event) {
return WatchSensorSummary.fromJson(_stringObjectMap(event));
});
}
@override
Stream<WatchSensorSample> get sensorSamples {
return _sensorSampleChannel
.receiveBroadcastStream()
.where((event) {
return event is Map;
})
.map((event) {
return WatchSensorSample.fromJson(_stringObjectMap(event));
});
}
@override
Stream<WatchBridgeConnectionEvent> get connectionEvents {
return _connectionChannel