DEV: Replace discourse-location with Ember version (#24365)
This commit is contained in:
parent
57584c38c0
commit
7c9cf666da
|
@ -1,4 +1,3 @@
|
||||||
import DiscourseLocation from "discourse/lib/discourse-location";
|
|
||||||
import Session from "discourse/models/session";
|
import Session from "discourse/models/session";
|
||||||
import Site from "discourse/models/site";
|
import Site from "discourse/models/site";
|
||||||
import TopicTrackingState, {
|
import TopicTrackingState, {
|
||||||
|
@ -34,8 +33,6 @@ export default {
|
||||||
const session = Session.current();
|
const session = Session.current();
|
||||||
app.register("service:session", session, { instantiate: false });
|
app.register("service:session", session, { instantiate: false });
|
||||||
|
|
||||||
app.register("location:discourse-location", DiscourseLocation);
|
|
||||||
|
|
||||||
startTracking(this.topicTrackingState);
|
startTracking(this.topicTrackingState);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,235 +0,0 @@
|
||||||
import EmberObject from "@ember/object";
|
|
||||||
import { guidFor } from "@ember/object/internals";
|
|
||||||
import $ from "jquery";
|
|
||||||
import { withoutPrefix } from "discourse-common/lib/get-url";
|
|
||||||
|
|
||||||
let popstateFired = false;
|
|
||||||
const supportsHistoryState = window.history && "state" in window.history;
|
|
||||||
const popstateCallbacks = [];
|
|
||||||
|
|
||||||
function _uuid() {
|
|
||||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
||||||
let r, v;
|
|
||||||
/* eslint-disable no-bitwise */
|
|
||||||
r = (Math.random() * 16) | 0;
|
|
||||||
v = c === "x" ? r : (r & 3) | 8;
|
|
||||||
/* eslint-enable no-bitwise */
|
|
||||||
return v.toString(16);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
`Ember.DiscourseLocation` implements the location API using the browser's
|
|
||||||
`history.pushState` API.
|
|
||||||
|
|
||||||
@class DiscourseLocation
|
|
||||||
@namespace Discourse
|
|
||||||
@extends @ember/object
|
|
||||||
*/
|
|
||||||
const DiscourseLocation = EmberObject.extend({
|
|
||||||
init() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
this.set("location", this.location || window.location);
|
|
||||||
|
|
||||||
this.initState();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Used to set state on first call to setURL
|
|
||||||
|
|
||||||
@method initState
|
|
||||||
*/
|
|
||||||
initState() {
|
|
||||||
const history = this.history || window.history;
|
|
||||||
if (history && history.scrollRestoration) {
|
|
||||||
history.scrollRestoration = "manual";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set("history", history);
|
|
||||||
|
|
||||||
let url = this.formatURL(this.getURL());
|
|
||||||
|
|
||||||
if (this.location && this.location.hash) {
|
|
||||||
url += this.location.hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.replaceState(url);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
Will be pre-pended to path upon state change
|
|
||||||
|
|
||||||
@property rootURL
|
|
||||||
@default '/'
|
|
||||||
*/
|
|
||||||
rootURL: "/",
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Returns the current `location.pathname` without rootURL
|
|
||||||
|
|
||||||
@method getURL
|
|
||||||
*/
|
|
||||||
getURL() {
|
|
||||||
let url = withoutPrefix(this.location.pathname);
|
|
||||||
const search = this.location.search || "";
|
|
||||||
url += search;
|
|
||||||
url = url.replace(/\/\//g, "/"); // remove extra slashes
|
|
||||||
return url;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Uses `history.pushState` to update the url without a page reload.
|
|
||||||
|
|
||||||
@method setURL
|
|
||||||
@param path {String}
|
|
||||||
*/
|
|
||||||
setURL(path) {
|
|
||||||
const state = this.getState();
|
|
||||||
path = this.formatURL(path);
|
|
||||||
|
|
||||||
if (state && state.path !== path) {
|
|
||||||
this.pushState(path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Uses `history.replaceState` to update the url without a page reload
|
|
||||||
or history modification.
|
|
||||||
|
|
||||||
@method replaceURL
|
|
||||||
@param path {String}
|
|
||||||
*/
|
|
||||||
replaceURL(path) {
|
|
||||||
const state = this.getState();
|
|
||||||
path = this.formatURL(path);
|
|
||||||
|
|
||||||
if (!state || state.path !== path) {
|
|
||||||
this.replaceState(path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Get the current `history.state`
|
|
||||||
Polyfill checks for native browser support and falls back to retrieving
|
|
||||||
from a private _historyState variable
|
|
||||||
|
|
||||||
@method getState
|
|
||||||
*/
|
|
||||||
getState() {
|
|
||||||
return supportsHistoryState ? this.history.state : this._historyState;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Pushes a new state
|
|
||||||
|
|
||||||
@method pushState
|
|
||||||
@param path {String}
|
|
||||||
*/
|
|
||||||
pushState(path) {
|
|
||||||
const state = { path, uuid: _uuid() };
|
|
||||||
|
|
||||||
// store state if browser doesn't support `history.state`
|
|
||||||
if (!supportsHistoryState) {
|
|
||||||
this._historyState = state;
|
|
||||||
} else {
|
|
||||||
this.history.pushState(state, null, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// used for webkit workaround
|
|
||||||
this._previousURL = this.getURL();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Replaces the current state
|
|
||||||
|
|
||||||
@method replaceState
|
|
||||||
@param path {String}
|
|
||||||
*/
|
|
||||||
replaceState(path) {
|
|
||||||
const state = { path, uuid: _uuid() };
|
|
||||||
|
|
||||||
// store state if browser doesn't support `history.state`
|
|
||||||
if (!supportsHistoryState) {
|
|
||||||
this._historyState = state;
|
|
||||||
} else {
|
|
||||||
this.history.replaceState(state, null, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// used for webkit workaround
|
|
||||||
this._previousURL = this.getURL();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Register a callback to be invoked whenever the browser
|
|
||||||
history changes, including using forward and back buttons.
|
|
||||||
|
|
||||||
@method onUpdateURL
|
|
||||||
@param callback {Function}
|
|
||||||
*/
|
|
||||||
onUpdateURL(callback) {
|
|
||||||
const guid = guidFor(this);
|
|
||||||
|
|
||||||
$(window).on(`popstate.ember-location-${guid}`, () => {
|
|
||||||
const url = this.getURL();
|
|
||||||
|
|
||||||
// Ignore initial page load popstate event in Chrome
|
|
||||||
if (!popstateFired) {
|
|
||||||
popstateFired = true;
|
|
||||||
if (url === this._previousURL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
popstateCallbacks.forEach((cb) => cb(url));
|
|
||||||
callback(url);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
@private
|
|
||||||
|
|
||||||
Used when using `{{action}}` helper. The url is always appended to the rootURL.
|
|
||||||
|
|
||||||
@method formatURL
|
|
||||||
@param url {String}
|
|
||||||
*/
|
|
||||||
formatURL(url) {
|
|
||||||
let rootURL = this.rootURL;
|
|
||||||
|
|
||||||
if (url !== "") {
|
|
||||||
rootURL = rootURL.replace(/\/$/, "");
|
|
||||||
|
|
||||||
if (rootURL.length > 0 && url.startsWith(rootURL + "/")) {
|
|
||||||
rootURL = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rootURL + url;
|
|
||||||
},
|
|
||||||
|
|
||||||
willDestroy() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
const guid = guidFor(this);
|
|
||||||
$(window).off(`popstate.ember-location-${guid}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default DiscourseLocation;
|
|
|
@ -159,6 +159,8 @@ const DiscourseURL = EmberObject.extend({
|
||||||
path = this.router.currentURL.replace(/#.*$/, "") + path;
|
path = this.router.currentURL.replace(/#.*$/, "") + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = withoutPrefix(path);
|
||||||
|
|
||||||
if (this.router.currentURL !== path) {
|
if (this.router.currentURL !== path) {
|
||||||
// Always use replaceState in the next runloop to prevent weird routes changing
|
// Always use replaceState in the next runloop to prevent weird routes changing
|
||||||
// while URLs are loading. For example, while a topic loads it sets `currentPost`
|
// while URLs are loading. For example, while a topic loads it sets `currentPost`
|
||||||
|
|
|
@ -5,7 +5,7 @@ import getURL from "discourse-common/lib/get-url";
|
||||||
import applyRouterHomepageOverrides from "./lib/homepage-router-overrides";
|
import applyRouterHomepageOverrides from "./lib/homepage-router-overrides";
|
||||||
|
|
||||||
class BareRouter extends EmberRouter {
|
class BareRouter extends EmberRouter {
|
||||||
location = isTesting() ? "none" : "discourse-location";
|
location = isTesting() ? "none" : "history";
|
||||||
|
|
||||||
setupRouter() {
|
setupRouter() {
|
||||||
const didSetup = super.setupRouter(...arguments);
|
const didSetup = super.setupRouter(...arguments);
|
||||||
|
|
Loading…
Reference in New Issue