import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'url_replacer.g.dart'; /// Replaces the browser URL of the current page without a new history entry /// and without rebuilding the page (so state, scroll position and focus stay). /// /// Web only: on other platforms there is no visible URL, nothing happens. /// The router state is updated inside `Router.neglect` (no history entry from /// the router), the address bar is replaced with /// `SystemNavigator.routeInformationUpdated(replace: true)`. class UrlReplacer { const UrlReplacer({this.isWeb = kIsWeb}); /// Whether to write at all (injectable for tests). final bool isWeb; void replace(BuildContext context, Uri uri) { if (!isWeb) { return; } final router = GoRouter.maybeOf(context); if (router != null) { final current = router.routeInformationProvider.value.uri; if (current != uri) { Router.neglect(context, () => router.go(uri.toString())); } } unawaited(SystemNavigator.routeInformationUpdated(uri: uri, replace: true)); } } /// Override in tests. @Riverpod(keepAlive: true) UrlReplacer urlReplacer(Ref ref) => const UrlReplacer();