Index: runtime/observatory/lib/src/app/location_manager.dart |
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart |
index 86e71e5ef9ab2f11b911e3df655cb789aeb1dd02..14f8de9eb3fa75064c22ce43a655b7a049da098d 100644 |
--- a/runtime/observatory/lib/src/app/location_manager.dart |
+++ b/runtime/observatory/lib/src/app/location_manager.dart |
@@ -4,11 +4,48 @@ |
part of app; |
-abstract class LocationManager extends Observable { |
- final _initialPath = '/vm'; |
- ObservatoryApplication _app; |
+/// Utility class to decode and encode the fragment (starts with '#') portion |
+/// of a url, including any query parameters. |
+class FragmentUri { |
turnidge
2015/04/07 21:24:31
Do we need to introduce this class? What if we ju
Cutch
2015/04/14 21:45:15
I've redone this part of the CL.
|
+ String _path; |
+ String get path => _path; |
+ final Map<String, String> parameters = new Map<String, String>(); |
+ |
+ FragmentUri(String url) { |
+ // Chop off leading '#'. |
+ if (url.startsWith('#')) { |
+ url = url.substring(1); |
+ } |
+ var queryStringIndex = url.indexOf('?'); |
+ if (queryStringIndex == -1) { |
+ _path = url; |
+ } else { |
+ _path = url.substring(0, queryStringIndex); |
+ parameters.addAll( |
+ Uri.splitQueryString(url.substring(queryStringIndex + 1))); |
+ } |
+ } |
- String _lastUrl; |
+ FragmentUri.from(FragmentUri other) { |
+ _path = other._path; |
+ parameters.addAll(other.parameters); |
+ } |
+ |
+ String toString() { |
+ if (parameters.isEmpty) { |
+ return '#$_path'; |
+ } |
+ var encodedParameters = new Uri(queryParameters: parameters).query; |
+ return '#${_path}?${encodedParameters}'; |
+ } |
+} |
+ |
+class LocationManager extends Observable { |
+ final _defaultPath = '/vm'; |
+ ObservatoryApplication _app; |
+ FragmentUri _fragment; |
+ FragmentUri get fragment => _fragment; |
+ String _url; |
void _init(ObservatoryApplication app) { |
// Called once. |
@@ -16,33 +53,34 @@ abstract class LocationManager extends Observable { |
_app = app; |
// Register for history events. |
window.onPopState.listen(_onLocationChange); |
- _onStartup(); |
+ |
+ var applicationPath = '${window.location.hash}'; |
+ if ((window.location.hash == '') || (window.location.hash == '#')) { |
+ // Observatory has loaded but no application path has been specified, |
+ // use the default. |
+ applicationPath = '#${_defaultPath}'; |
+ } |
+ // Update current application path. |
+ window.history.replaceState(applicationPath, |
+ document.title, |
+ applicationPath); |
+ _updateCurrent(applicationPath); |
+ _go(applicationPath); |
} |
- void _onStartup(); |
- void _onLocationChange(PopStateEvent event); |
+ void _updateCurrent(String url) { |
+ _url = url; |
+ _fragment = new FragmentUri(url); |
+ } |
void _pushUrl(String url) { |
- if (_lastUrl != url) { |
+ if (_url != url) { |
Logger.root.info('Navigated to ${url}'); |
window.history.pushState(url, document.title, url); |
- _lastUrl = url; |
+ _updateCurrent(url); |
} |
} |
- /// Go to a specific url. |
- void go(String url) { |
- if ((url != makeLink('/vm-connect/')) && _app.vm == null) { |
- if (!window.confirm('Connection with VM has been lost. ' |
- 'Proceeding will lose current page.')) { |
- return; |
- } |
- url = makeLink('/vm-connect/'); |
- } |
- _pushUrl(url); |
- _go(url); |
- } |
- |
void _go(String url) { |
// Chop off leading '#'. |
if (url.startsWith('#')) { |
@@ -65,14 +103,27 @@ abstract class LocationManager extends Observable { |
_app._visit(url, args); |
} |
- /// Go back. |
- void back() { |
- window.history.go(-1); |
+ /// Go to a specific url. |
+ void go(String url) { |
+ if ((url != makeLink('/vm-connect/')) && _app.vm == null) { |
+ if (!window.confirm('Connection with VM has been lost. ' |
+ 'Proceeding will lose current page.')) { |
+ return; |
+ } |
+ url = makeLink('/vm-connect/'); |
+ } |
+ _pushUrl(url); |
+ _go(url); |
} |
- /// Go forward. |
- void forward() { |
- window.history.go(1); |
+ /// Starting with the current url, update all parameters present in |
+ /// [updatedParameters], then generate a new url and navigate to that. |
+ goParameter(Map updatedParameters) { |
+ var fragment = new FragmentUri.from(_fragment); |
+ updatedParameters.forEach((k, v) { |
+ fragment.parameters[k] = v; |
+ }); |
+ go(fragment.toString()); |
} |
/// Handle clicking on an application url link. |
@@ -89,50 +140,12 @@ abstract class LocationManager extends Observable { |
event.preventDefault(); |
} |
- /// Given an application url, generate a link. |
- String makeLink(String url); |
-} |
- |
-/// Uses location.hash to encode application urls. |
-class HashLocationManager extends LocationManager { |
- void _onStartup() { |
- String initialPath = '${window.location.hash}'; |
- if ((window.location.hash == '') || (window.location.hash == '#')) { |
- initialPath = '#${_initialPath}'; |
- } |
- window.history.pushState(initialPath, document.title, initialPath); |
+ /// Called whenever the browser changes the location bar (e.g. back button). |
+ void _onLocationChange(PopStateEvent event) { |
+ _updateCurrent(window.location.hash); |
_go(window.location.hash); |
} |
- void _onLocationChange(PopStateEvent _) { |
- _go(window.location.hash); |
- } |
- |
- /// Given an application url, generate a link for an anchor tag. |
- String makeLink(String url) { |
- return '#$url'; |
- } |
-} |
- |
-/// Uses location.pathname to encode application urls. Requires server side |
-/// rewriting to support copy and paste linking. pub serve makes this hard. |
-/// STATUS: Work in progress. |
-class LinkLocationManager extends LocationManager { |
- void _onStartup() { |
- Logger.root.warning('Using untested LinkLocationManager'); |
- String initialPath = window.location.pathname; |
- if ((window.location.pathname == '/index.html') || |
- (window.location.pathname == '/')) { |
- initialPath = '/vm'; |
- } |
- window.history.replaceState(initialPath, document.title, initialPath); |
- _go(window.location.pathname); |
- } |
- |
- void _onLocationChange(PopStateEvent _) { |
- _go(window.location.pathname); |
- } |
- |
- /// Given an application url, generate a link for an anchor tag. |
- String makeLink(String url) => url; |
+ /// Given an application url, generate a link. |
+ String makeLink(String url) => '#$url'; |
} |