Skip to content

v2.0.0 — Architecture deepening

Latest

Choose a tag to compare

@phanbaohuy96 phanbaohuy96 released this 18 May 11:34
· 76 commits to master since this release
822c585

Seven-stage architectural deepening pass across the template. Drives shallow modules toward real seams, ships a worked end-to-end auth example, and adds the canonical adapter for `RouteProviderInterceptor`. Also introduces `CONTEXT.md` capturing the template's architectural vocabulary.

Full details: #25.

Highlights

  • Storage seam. `CoreLocalDataManager` / `LocalDataManager` now own `SharedPreferences` + `FlutterSecureStorage` directly; the pass-through `*PreferencesHelper` layers are gone. Hive runtime pulled (init, re-export, empty marker).
  • Auth demo. Replaces the role-picker prototype with a phone + password flow that demonstrates the full data → domain → presentation slice. `MockAuthRemoteSource` is the single swap point for plugging in a real backend. Demo credentials: `0911357924/password1` and `0987654321/password2`.
  • `AuthenticationCoordinator.openSignIn` grew a `returnTo` parameter and a pre-nav token guard — short-circuits the form when already authenticated, threads the redirect target back to the screen via the new typed `SigninRouteArgs` (works on native push, web push, and deep links).
  • `AuthGateRouteInterceptor` is the canonical adapter for `RouteProviderInterceptor`: gates every provider except the auth route, redirects unauthenticated callers to `/signin?redirect=`. Sync token check via `CoreLocalDataManager.isAuthenticated`; cache bootstrapped once in `app_delegate`.
  • Codegen templates stop emitting one-line coordinators for single-screen modules; repository / common usecase impls now teach the layer-translation pattern (try/catch, DTO→entity, error normalisation — each as a structured TODO).
  • `AppBlocBase` retired — blocs extend `CoreBlocBase` directly.

Breaking changes for forks

  • `AuthResponse`, `AuthSuccessResponse`, and `LoginResultType` are removed. `AuthUsecase.loginWithPhoneNumberPassword` now returns `Future<UserModel?>`.
  • `SigninBloc` events (`UpdatePhoneEvent` / `UpdatePasswordEvent` / `LoginEvent`) and states (`SigninInitial` / `LoginSuccess` / `LoginFailed`) replaced the role-picker shape entirely. `_StateData` carries `phone` and `password`, nothing else.
  • `AppBlocBase` is gone. Move existing blocs to `CoreBlocBase`.
  • `CorePreferencesHelper` / `PreferencesHelper` and their impl/abstract pair are deleted. Inject `CoreLocalDataManager` or `LocalDataManager` directly.
  • `CoreLocalHiveData` (the empty marker interface) and `Hive.initFlutter()` are gone. Re-add only if you actually use Hive.
  • l10n keys `userRole`, `pleaseSelectARoleBeforeLoginMsg`, `thisRoleIsNotSupportedYet` are removed; `loginFailed` reworded. Added: `phoneNumber`, `password`, `phoneNumberHint`, `passwordHint`, `phoneRequired`, `passwordRequired`.
  • The module generator's listing and common templates no longer emit a `*_coordinator.dart` file. Existing single-screen coordinators in your fork can be safely deleted; call routes directly via `pushBehavior.push(context, …)`.

Bug fixes (uncovered by Playwright e2e on the new auth flow)

  • `InputContainer(isPassword: true)` would crash with `Unexpected null value` when no `controller` was supplied — `SignInScreenState` now owns explicit controllers. The latent widget-level null-bang at `input_container.dart:352` is left for a follow-up.
  • `LocalDataManager` was bound as `@injectable` (factory), so every DI lookup returned a fresh instance with an empty token cache and the auth gate could never see a logged-in user. Both the class and the `CoreLocalDataManager` bridge are now `@lazySingleton`.

Verified end-to-end (Playwright)

  • Cold-launch signin (success + `LoginFailed` branch)
  • Deep-link gate (`/dev-mode-dashboard` → `/signin?redirect=…` → back to original)
  • Pre-nav guard (404 → "Back to Homepage" → coordinator skips form when token cached)
  • Module generator output (listing module: no coordinator file)