feat: implement watchPositions() tag position stream

This commit is contained in:
2026-05-19 21:07:11 +02:00
parent dffe8d4f5e
commit e0a3d5e481
2 changed files with 40 additions and 13 deletions
@@ -38,19 +38,42 @@ class PhoenixTagRepository implements TagRepository {
Future<void> deleteTag(int id) => tagClient.deleteTag(id);
@override
Stream<List<TagPosition>> watchPositions() =>
realtime.channel('tags').map((payload) {
final list = payload['positions'] as List<dynamic>? ?? [];
return list.map((j) {
final m = j as Map<String, dynamic>;
return TagPosition(
tagId: m['tag_id'] as String,
name: m['name'] as String,
color: m['color'] as String,
roomId: m['room_id'] as int?,
);
}).toList();
});
Stream<List<TagPosition>> watchPositions() async* {
var tagMap = await _fetchTagMap();
await for (final occupancy in watchRoomOccupancy()) {
// Re-fetch on every occupancy change so name/color edits and new tags
// are reflected without restarting the stream.
tagMap = await _fetchTagMap();
final positions = <TagPosition>[];
for (final entry in occupancy.entries) {
for (final tagId in entry.value) {
final tag = tagMap[tagId];
positions.add(TagPosition(
tagId: tagId,
name: tag?.name ?? tagId,
color: tag?.color ?? _colorForTagId(tagId),
roomId: entry.key,
));
}
}
yield positions;
}
}
Future<Map<String, Tag>> _fetchTagMap() async {
final raw = await tagClient.getTags();
return {
for (final j in raw.cast<Map<String, dynamic>>())
j['tag_id'] as String: Tag.fromJson(j),
};
}
static String _colorForTagId(String tagId) {
final hash = tagId.codeUnits.fold(0, (h, c) => (h * 31 + c) & 0xFFFFFF);
return '#${hash.toRadixString(16).padLeft(6, '0')}';
}
@override
Stream<ParticleSnapshot> watchParticleCloud(String tagId) =>