Unverified Commit 43407cf1 authored by Vasiliy Ditsyak's avatar Vasiliy Ditsyak Committed by GitHub

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
parent da0f9a99
...@@ -46,6 +46,7 @@ class PathUrlStrategy extends ui_web.HashUrlStrategy { ...@@ -46,6 +46,7 @@ class PathUrlStrategy extends ui_web.HashUrlStrategy {
/// interactions. /// interactions.
PathUrlStrategy([ PathUrlStrategy([
super.platformLocation, super.platformLocation,
this.includeHash = false,
]) : _platformLocation = platformLocation, ]) : _platformLocation = platformLocation,
_basePath = stripTrailingSlash(extractPathname(checkBaseHref( _basePath = stripTrailingSlash(extractPathname(checkBaseHref(
platformLocation.getBaseHref(), platformLocation.getBaseHref(),
...@@ -54,9 +55,20 @@ class PathUrlStrategy extends ui_web.HashUrlStrategy { ...@@ -54,9 +55,20 @@ class PathUrlStrategy extends ui_web.HashUrlStrategy {
final ui_web.PlatformLocation _platformLocation; final ui_web.PlatformLocation _platformLocation;
final String _basePath; 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 @override
String getPath() { 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)) { if (_basePath.isNotEmpty && path.startsWith(_basePath)) {
return ensureLeadingSlash(path.substring(_basePath.length)); return ensureLeadingSlash(path.substring(_basePath.length));
} }
......
...@@ -129,5 +129,5 @@ class PathUrlStrategy extends HashUrlStrategy { ...@@ -129,5 +129,5 @@ class PathUrlStrategy extends HashUrlStrategy {
/// ///
/// The [PlatformLocation] parameter is useful for testing to mock out browser /// The [PlatformLocation] parameter is useful for testing to mock out browser
/// integrations. /// integrations.
const PathUrlStrategy([PlatformLocation? _]); const PathUrlStrategy([PlatformLocation? _, bool __ = false,]);
} }
...@@ -80,17 +80,34 @@ void main() { ...@@ -80,17 +80,34 @@ void main() {
expect(strategy.getPath(), '/bar'); 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.baseHref = 'https://example.com/foo/';
location.pathname = '/foo/bar'; location.pathname = '/foo/bar';
final PathUrlStrategy strategy = PathUrlStrategy(location); 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'; location.search = '?q=1';
expect(strategy.getPath(), '/bar?q=1'); expect(strategy.getPath(), '/bar?q=1');
location.search = '?q=1&t=r'; location.search = '?q=1&t=r';
expect(strategy.getPath(), '/bar?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', () { test('empty route name is ok', () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment