Skip to content

refactor: replace FutureProvider caching with Drift stream-based reactivity#238

Open
rileychh wants to merge 5 commits intomainfrom
stream-providers
Open

refactor: replace FutureProvider caching with Drift stream-based reactivity#238
rileychh wants to merge 5 commits intomainfrom
stream-providers

Conversation

@rileychh
Copy link
Copy Markdown
Member

Closes #220

Summary

  • Replace getX({refresh})/fetchWithTtl pattern with watchX() streams backed by Drift .watch() queries and refreshX() imperative methods for pull-to-refresh
  • Streams emit cached data immediately, background-fetch when stale, and auto-propagate DB changes — eliminating manual ref.invalidate() calls across screens
  • userAvatarProvider watches avatarFilename via .select so background profile refreshes automatically update the avatar
  • Delete fetchWithTtl utility and its tests (each method now has its own hard-coded TTL const)
  • Simplify main.dart startup to a direct DB query instead of getUser()

Future tasks

  • No refresh indicator during background TTL refresh — would need a side-channel loading state
  • Handle offline situations — global connectivityProvider for offline banners (tracked in AGENTS.md)

Test plan

  • Login → profile card, course table, and owner indicator populate automatically
  • Pull-to-refresh on profile tab → profile + avatar update
  • Pull-to-refresh on course table tab → semesters + course table update
  • Clear cache in danger zone → data clears, streams auto-refetch
  • Clear cookies → interact with data → silent re-auth
  • Change avatar externally, let user cache expire, restart app → avatar updates automatically
  • Logout → all data clears, redirects to login
  • Tab switching rapidly → no duplicate fetches or errors

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 24, 2026

PR Preview Builds

Build Number: 781
Commit: 9723250
Message: fix: key courseTableProvider by semester ID to prevent unnecessary recreations

Deploy

  • Android (Firebase App Distribution)
  • iOS (TestFlight)

Android (Firebase App Distribution)

Install build 781

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors repository/provider data flow from FutureProvider + manual TTL caching to Drift .watch()-backed StreamProvider reactivity, aiming to make DB the single source of truth and reduce manual provider invalidation across screens.

Changes:

  • Replace getX({refresh}) patterns with watchX() streams + refreshX() imperative methods across Auth/Course/Student repositories.
  • Update UI providers and screens to consume StreamProviders, simplifying refresh flows and removing most manual invalidation.
  • Remove fetchWithTtl utility (and its tests) and simplify app startup session detection to a direct DB lookup.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
test/utils/fetch_with_ttl_test.dart Removed tests for fetchWithTtl (utility deleted).
lib/utils/fetch_with_ttl.dart Deleted shared TTL helper in favor of per-repository TTL logic.
lib/screens/main/user_providers.dart Convert user profile to StreamProvider; avatar provider now rebuilds off avatarFilename changes.
lib/screens/main/profile/profile_screen.dart Simplify pull-to-refresh to refreshUser(); remove avatar invalidation after upload.
lib/screens/main/profile/profile_providers.dart Active registration provider now watches DB via stream.
lib/screens/main/profile/profile_danger_zone.dart Remove invalidations that are no longer needed with stream-based providers.
lib/screens/main/course_table/course_table_screen.dart Refresh now calls refreshSemesters() + refreshCourseTable(); remove manual invalidations.
lib/screens/main/course_table/course_table_providers.dart Switch semesters/course table providers to StreamProviders.
lib/repositories/auth_repository.dart Replace getUser() with watchUser() + refreshUser(); active registration now uses .watchSingleOrNull().
lib/repositories/course_repository.dart Introduce watchSemesters()/refreshSemesters() and watchCourseTable()/refreshCourseTable(); inline TTL for getCourse().
lib/repositories/student_repository.dart Replace getSemesterRecords() with watchSemesterRecords() + refreshSemesterRecords().
lib/main.dart Determine initial session via direct DB query instead of getUser().
AGENTS.md Update architecture documentation to reflect the new stream-based repository pattern.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Base automatically changed from withauth-coalesce to main March 24, 2026 17:42
@rileychh-dokploy-riley-ntut-npc
Copy link
Copy Markdown

rileychh-dokploy-riley-ntut-npc bot commented Mar 25, 2026

Dokploy Preview Deployment

Name Status Preview Updated (UTC)
API Docs ✅ Done Preview URL 2026-03-25T11:14:30.312Z

…tivity

Replace getX({refresh})/fetchWithTtl pattern with watchX() streams backed
by Drift .watch() queries and refreshX() imperative methods for
pull-to-refresh. Streams emit cached data immediately, background-fetch
when stale, and auto-propagate DB changes — eliminating manual
ref.invalidate() calls across screens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

使用 Drift stream 實現 reactive 資料觀察

2 participants