watchSyllabus method

Stream<Syllabus?> watchSyllabus({
  1. required int offeringId,
  2. required String teacherId,
})

Watches the syllabus authored by teacherId for offering offeringId, refreshing it once per subscription (no staleness gate).

Emits the cached row immediately when present, then refreshes in the background; with no cached row it blocks on the first fetch instead, so the UI shows content (or a definitive "no syllabus") rather than flashing empty. The stream re-emits when the DB is updated. Emits null when the teacher hasn't submitted a syllabus (尚未登錄) or is unknown.

Implementation

Stream<Syllabus?> watchSyllabus({
  required int offeringId,
  required String teacherId,
}) async* {
  final teacher = await (_database.select(
    _database.teachers,
  )..where((t) => t.code.equals(teacherId))).getSingleOrNull();
  if (teacher == null) {
    yield null;
    return;
  }

  final query = _database.select(_database.syllabuses)
    ..where(
      (s) =>
          s.courseOffering.equals(offeringId) & s.teacher.equals(teacher.id),
    );

  // Fetch once per subscription. The guard stops the refresh's own write
  // from re-triggering the fetch on the re-emit.
  var refreshed = false;
  await for (final syllabus in query.watchSingleOrNull()) {
    if (syllabus == null && !refreshed) {
      refreshed = true;
      try {
        await refreshSyllabus(offeringId: offeringId, teacherId: teacherId);
        // Emit the freshly fetched row (or null on 尚未登錄) rather than the
        // stale null snapshot, before the stream re-emits.
        yield await query.getSingleOrNull();
        continue;
      } catch (_) {
        // Absorb: yield null below so the UI exits its loading state
      }
    }

    yield syllabus;

    if (syllabus != null && !refreshed) {
      refreshed = true;
      try {
        await refreshSyllabus(offeringId: offeringId, teacherId: teacherId);
      } catch (_) {
        // Absorb: stale content is shown via stream
      }
    }
  }
}