DEV: Replace discourse-location with Ember version (#24365)

This commit is contained in:
David Taylor 2023-11-23 15:40:24 +00:00 committed by GitHub
parent 57584c38c0
commit 7c9cf666da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 3 additions and 239 deletions

View File

@ -1,4 +1,3 @@
import DiscourseLocation from "discourse/lib/discourse-location";
import Session from "discourse/models/session";
import Site from "discourse/models/site";
import TopicTrackingState, {
@ -34,8 +33,6 @@ export default {
const session = Session.current();
app.register("service:session", session, { instantiate: false });
app.register("location:discourse-location", DiscourseLocation);
startTracking(this.topicTrackingState);
},

View File

@ -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;

View File

@ -159,6 +159,8 @@ const DiscourseURL = EmberObject.extend({
path = this.router.currentURL.replace(/#.*$/, "") + path;
}
path = withoutPrefix(path);
if (this.router.currentURL !== path) {
// 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`

View File

@ -5,7 +5,7 @@ import getURL from "discourse-common/lib/get-url";
import applyRouterHomepageOverrides from "./lib/homepage-router-overrides";
class BareRouter extends EmberRouter {
location = isTesting() ? "none" : "discourse-location";
location = isTesting() ? "none" : "history";
setupRouter() {
const didSetup = super.setupRouter(...arguments);