export function beginSession(session, nowTs = Date.now()) { session.status = "running"; session.startedAt = nowTs; session.endedAt = null; session.finishedByTimer = false; session.followUpStartedAt = null; session.pausedAt = null; session.totalPausedMs = 0; session.followUpPausedMs = 0; session.audioAnnouncements = []; return session; } export function finishSession(session, nowTs = Date.now()) { // Finishing while paused must fold the still-open pause segment into totalPausedMs the // same way resumeSession does - otherwise that final segment's duration is silently // dropped, and the session's own displayed elapsed time (getSessionTiming) keeps // growing after finish, since it would still be missing from totalPausedMs. if (session?.status === "paused" && session.pausedAt) { const pausedDuration = Math.max(0, nowTs - Number(session.pausedAt || nowTs)); session.totalPausedMs = Math.max(0, Number(session.totalPausedMs || 0)) + pausedDuration; } session.status = "finished"; session.endedAt = nowTs; session.finishedByTimer = false; session.followUpStartedAt = null; session.pausedAt = null; return session; } export function pauseSession(session, nowTs = Date.now()) { if (session?.status !== "running") return false; session.status = "paused"; session.pausedAt = nowTs; return true; } export function resumeSession(session, nowTs = Date.now()) { if (session?.status !== "paused") return false; const pausedDuration = Math.max(0, nowTs - Number(session.pausedAt || nowTs)); session.totalPausedMs = Math.max(0, Number(session.totalPausedMs || 0)) + pausedDuration; if (session.followUpStartedAt) { session.followUpPausedMs = Math.max(0, Number(session.followUpPausedMs || 0)) + pausedDuration; } session.pausedAt = null; session.status = "running"; return true; }