Problem
Currently, streak updates require a single session with duration >= 2 minutes. If a user does 1:30 of listening, stops, then starts a new session, the progress resets. The 1:30 is lost because each session is checked independently.
Also, the frontend polls all_language_streaks every 5 seconds waiting for the streak to update, which is wasteful especially when the user just started.
Proposed Solution
-
Track cumulative daily practice time on UserLanguage — add a practiced_today_ms column that update_activity_session increments on each update. The streak check becomes practiced_today_ms >= 120_000 instead of checking a single session's duration.
-
Return seconds_until_streak from all_language_streaks — the API already knows how much time has been accumulated. It can return the remaining seconds needed, so the frontend sets a single timeout instead of polling every 5 seconds.
Example response:
{
"code": "da",
"daily_streak": 17,
"practiced_today": false,
"seconds_until_streak": 85
}
-
Reset practiced_today_ms daily — either lazily (check date on read) or via the existing last_practiced date comparison.
Benefits
- Cumulative progress across sessions (no lost time)
- Smart polling (one timeout vs 5s interval)
- Cheap to compute (no cross-table session queries)
🤖 Generated with Claude Code
Problem
Currently, streak updates require a single session with duration >= 2 minutes. If a user does 1:30 of listening, stops, then starts a new session, the progress resets. The 1:30 is lost because each session is checked independently.
Also, the frontend polls
all_language_streaksevery 5 seconds waiting for the streak to update, which is wasteful especially when the user just started.Proposed Solution
Track cumulative daily practice time on
UserLanguage— add apracticed_today_mscolumn thatupdate_activity_sessionincrements on each update. The streak check becomespracticed_today_ms >= 120_000instead of checking a single session's duration.Return
seconds_until_streakfromall_language_streaks— the API already knows how much time has been accumulated. It can return the remaining seconds needed, so the frontend sets a single timeout instead of polling every 5 seconds.Example response:
{ "code": "da", "daily_streak": 17, "practiced_today": false, "seconds_until_streak": 85 }Reset
practiced_today_msdaily — either lazily (check date on read) or via the existinglast_practiceddate comparison.Benefits
🤖 Generated with Claude Code