41 lines
1.3 KiB
Dart
41 lines
1.3 KiB
Dart
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();
|