fix(inventory): merge draft + list watch into one subscription

InventoryCubit subscribed to watchInventory() and watchDrafts()
separately — two overlapping StreamGroups (both watching attachments)
re-emitted in a tight loop that starved the event loop and hung widget
tests' pumpAndSettle for 10+ minutes (home/inventory/quick-add all
timed out). Replace both with a single watchInventoryView() stream that
loads the catalogued list and the draft tray from one StreamGroup.

Full widget suite no longer hangs: 165 pass. One unrelated failure
remains in the v8 variety edit sheet (Save button pushed off-screen by
new fields).
This commit is contained in:
vjrj 2026-07-09 21:33:48 +02:00
parent 6809dc6143
commit 7f9f5c065b
2 changed files with 31 additions and 8 deletions

View file

@ -365,6 +365,27 @@ class VarietyRepository {
return triggers.asyncMap((_) => _loadInventory());
}
/// The whole inventory screen in one reactive subscription: the catalogued
/// list and the draft tray, from a single [StreamGroup]. The cubit MUST use
/// this rather than subscribing to [watchInventory] and [watchDrafts]
/// separately two overlapping StreamGroups (both watching `attachments`)
/// re-emit in a tight loop that starves the event loop and hangs widget
/// tests' `pumpAndSettle`.
Stream<({List<VarietyListItem> items, List<VarietyListItem> drafts})>
watchInventoryView() {
final triggers = StreamGroup.merge<void>([
(_db.select(
_db.varieties,
)..where((v) => v.isDeleted.equals(false))).watch().map((_) {}),
_db.select(_db.attachments).watch().map((_) {}),
_db.select(_db.species).watch().map((_) {}),
_db.select(_db.lots).watch().map((_) {}),
]);
return triggers.asyncMap(
(_) async => (items: await _loadInventory(), drafts: await _loadDrafts()),
);
}
Future<List<VarietyListItem>> _loadInventory() async {
final rows =
await (_db.select(_db.varieties)