Add fallback UI feedback for URL launch failures
epic-no-access-screen-foundation-task-006 — Extend UrlLauncherUtil so that when a URL cannot be opened (unsupported scheme, no handler installed, platform error) it triggers a standardised snackbar or dialog feedback via a provided BuildContext callback. This prevents silent failures when a user taps the admin portal link.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Prefer an optional `onFailure` callback over passing `BuildContext` directly into the utility class—this keeps the utility layer decoupled from the widget tree and easier to test without a full widget pump. The callback signature `void Function(UrlLaunchResult result)` gives callers full flexibility (snackbar, dialog, log, etc.). The no-access screen widget will provide the concrete implementation that shows the snackbar. If the project has a centralised `AppSnackbar.show(context, message)` helper, use it here for consistency.
Ensure the user-facing message is distinct for `unsupported` (e.g., 'No app found to open this link') vs `error` (e.g., 'Could not open link. Try again later.'). Both messages need to be accessible to screen readers—`SnackBar.content` should be a `Text` widget with correct semantics.
Testing Requirements
Covered by `epic-no-access-screen-foundation-task-007`. For this subtask, add a widget test that pumps a minimal `Scaffold` wrapping a button that calls `launchUrlWithFeedback` with a mocked failing platform, then asserts that a `SnackBar` with the expected message text appears in the widget tree using `find.byType(SnackBar)` and `find.text(...)`. Verify the success path does NOT produce a snackbar.
Supabase remote config may be unavailable at app startup (network error, cold start), causing the repository to return no blocked-role list. If the fallback is empty, blocked users could access the app.
Mitigation & Contingency
Mitigation: Define a local constants fallback list of blocked roles compiled into the app binary. Remote config enriches or overrides this list when available.
Contingency: If remote config repeatedly fails in production, pin the blocked-role list to local constants only and disable remote override until the Supabase config endpoint is stabilised.
url_launcher package behaviour differs between iOS and Android (e.g. canLaunchUrl returning false on some Android configurations), leading to silent failures when the admin portal link is tapped.
Mitigation & Contingency
Mitigation: Run canLaunchUrl check before every launch attempt and surface a descriptive inline error message (e.g. 'Could not open link — visit admin.example.org manually') when the check fails.
Contingency: If canLaunchUrl is consistently unreliable on a target platform, replace the tap-to-open pattern with a copyable text field showing the URL as a fallback.