Access to fragment in router state on page refresh (#131123)

This PR fixes the issue #108614 
Particularly this behaviour https://github.com/flutter/flutter/issues/108614#issuecomment-1645231915
This commit is contained in:
Vasiliy Ditsyak 2023-09-18 23:12:08 +02:00 committed by GitHub
parent da0f9a997a
commit 43407cf155
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 4 deletions

View file

@ -46,6 +46,7 @@ class PathUrlStrategy extends ui_web.HashUrlStrategy {
/// interactions.
PathUrlStrategy([
super.platformLocation,
this.includeHash = false,
]) : _platformLocation = platformLocation,
_basePath = stripTrailingSlash(extractPathname(checkBaseHref(
platformLocation.getBaseHref(),
@ -54,9 +55,20 @@ class PathUrlStrategy extends ui_web.HashUrlStrategy {
final ui_web.PlatformLocation _platformLocation;
final String _basePath;
/// There were an issue with url #hash which disappears from URL on first start of the web application
/// This flag allows to preserve that hash and was introduced mainly to preserve backward compatibility
/// with existing applications that rely on a full match on the path. If someone navigates to
/// /profile or /profile#foo, they both will work without this flag otherwise /profile#foo won't match
/// with the /profile route name anymore because the hash became part of the path.
///
/// This flag solves the edge cases when using auth provider which redirects back to the app with
/// token in redirect URL as /#access_token=bla_bla_bla
final bool includeHash;
@override
String getPath() {
final String path = _platformLocation.pathname + _platformLocation.search;
final String? hash = includeHash ? _platformLocation.hash : null;
final String path = _platformLocation.pathname + _platformLocation.search + (hash ?? '');
if (_basePath.isNotEmpty && path.startsWith(_basePath)) {
return ensureLeadingSlash(path.substring(_basePath.length));
}

View file

@ -129,5 +129,5 @@ class PathUrlStrategy extends HashUrlStrategy {
///
/// The [PlatformLocation] parameter is useful for testing to mock out browser
/// integrations.
const PathUrlStrategy([PlatformLocation? _]);
const PathUrlStrategy([PlatformLocation? _, bool __ = false,]);
}

View file

@ -80,17 +80,34 @@ void main() {
expect(strategy.getPath(), '/bar');
});
test('gets path correctly in the presence of query params', () {
test('gets path correctly in the presence of query params and omits fragment if no flag specified', () {
location.baseHref = 'https://example.com/foo/';
location.pathname = '/foo/bar';
final PathUrlStrategy strategy = PathUrlStrategy(location);
location.search = '?q=1';
expect(strategy.getPath(), '/bar?q=1');
location.search = '?q=1&t=r';
expect(strategy.getPath(), '/bar?q=1&t=r');
location.hash = '#fragment=1';
expect(strategy.getPath(), '/bar?q=1&t=r');
});
test('gets path correctly in the presence of query params and fragment', () {
location.baseHref = 'https://example.com/foo/';
location.pathname = '/foo/bar';
final PathUrlStrategy strategy = PathUrlStrategy(location, true);
location.search = '?q=1';
expect(strategy.getPath(), '/bar?q=1');
location.search = '?q=1&t=r';
expect(strategy.getPath(), '/bar?q=1&t=r');
location.hash = '#fragment=1';
expect(strategy.getPath(), '/bar?q=1&t=r#fragment=1');
});
test('empty route name is ok', () {