ENGLISH·COURSE API
    Preparing search index...
    • The one rule for "how far is this learner through this lesson", read by every surface that shows progress or completion.

      Parameters

      • lessonId: { lessonId: string & $brand<"LessonId">; durationSeconds: number }

        The lesson to report on

      Returns LessonWatchState

      The watched fraction and whether the lesson counts as complete

      Completion has two producers — the Mark as complete button and playback crossing the finish threshold — and this hook is where they are combined. Keeping the union in one place is what stops a row, an outline entry and a module card from disagreeing about the same lesson.

      Deriving completion from the saved position, rather than reading only what the tracker stored, is also what lights up positions saved before the finish rule existed: no migration, no backfill write.

      A complete lesson reports a watchedFraction of 1 whatever its stored position, so "finished" and "nearly finished" are never drawn identically.

      A lesson with no runtime — every reading lesson — has no watched fraction, and its completion is whatever the tracker says.

      Browser-side only — do NOT call from a Server Component.

      const { watchedFraction, isComplete } = useLessonWatchState({
      lessonId,
      durationSeconds,
      });
      if (watchedFraction === 0 && !isComplete) return null;