@webqit/webflo 0.11.61 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/{Context.js → AbstractContext.js} +1 -9
- package/src/deployment-pi/origins/index.js +1 -1
- package/src/index.js +1 -9
- package/src/runtime-pi/HttpEvent.js +101 -81
- package/src/runtime-pi/HttpUser.js +126 -0
- package/src/runtime-pi/MessagingOverBroadcast.js +9 -0
- package/src/runtime-pi/MessagingOverChannel.js +85 -0
- package/src/runtime-pi/MessagingOverSocket.js +106 -0
- package/src/runtime-pi/MultiportMessagingAPI.js +81 -0
- package/src/runtime-pi/WebfloCookieStorage.js +27 -0
- package/src/runtime-pi/WebfloEventTarget.js +39 -0
- package/src/runtime-pi/WebfloMessageEvent.js +58 -0
- package/src/runtime-pi/WebfloMessagingAPI.js +69 -0
- package/src/runtime-pi/{Router.js → WebfloRouter.js} +3 -34
- package/src/runtime-pi/WebfloRuntime.js +52 -0
- package/src/runtime-pi/WebfloStorage.js +109 -0
- package/src/runtime-pi/client/ClientMessaging.js +5 -0
- package/src/runtime-pi/client/Context.js +2 -6
- package/src/runtime-pi/client/CookieStorage.js +17 -0
- package/src/runtime-pi/client/Router.js +3 -13
- package/src/runtime-pi/client/SessionStorage.js +33 -0
- package/src/runtime-pi/client/Url.js +24 -72
- package/src/runtime-pi/client/WebfloClient.js +544 -0
- package/src/runtime-pi/client/WebfloRootClient1.js +179 -0
- package/src/runtime-pi/client/WebfloRootClient2.js +109 -0
- package/src/runtime-pi/client/WebfloSubClient.js +165 -0
- package/src/runtime-pi/client/Workport.js +89 -161
- package/src/runtime-pi/client/generate.js +3 -3
- package/src/runtime-pi/client/index.js +13 -18
- package/src/runtime-pi/client/worker/ClientMessaging.js +5 -0
- package/src/runtime-pi/client/worker/Context.js +2 -6
- package/src/runtime-pi/client/worker/CookieStorage.js +17 -0
- package/src/runtime-pi/client/worker/SessionStorage.js +13 -0
- package/src/runtime-pi/client/worker/WebfloWorker.js +294 -0
- package/src/runtime-pi/client/worker/Workport.js +13 -73
- package/src/runtime-pi/client/worker/index.js +7 -18
- package/src/runtime-pi/index.js +1 -8
- package/src/runtime-pi/server/ClientMessaging.js +18 -0
- package/src/runtime-pi/server/ClientMessagingRegistry.js +57 -0
- package/src/runtime-pi/server/Context.js +2 -6
- package/src/runtime-pi/server/CookieStorage.js +17 -0
- package/src/runtime-pi/server/Router.js +2 -68
- package/src/runtime-pi/server/SessionStorage.js +53 -0
- package/src/runtime-pi/server/WebfloServer.js +755 -0
- package/src/runtime-pi/server/index.js +7 -18
- package/src/runtime-pi/util-http.js +268 -32
- package/src/runtime-pi/xURL.js +25 -22
- package/src/runtime-pi/xfetch.js +2 -2
- package/src/runtime-pi/Application.js +0 -29
- package/src/runtime-pi/Cookies.js +0 -82
- package/src/runtime-pi/Runtime.js +0 -21
- package/src/runtime-pi/client/Application.js +0 -76
- package/src/runtime-pi/client/Runtime.js +0 -525
- package/src/runtime-pi/client/createStorage.js +0 -58
- package/src/runtime-pi/client/worker/Application.js +0 -44
- package/src/runtime-pi/client/worker/Runtime.js +0 -275
- package/src/runtime-pi/server/Application.js +0 -101
- package/src/runtime-pi/server/Runtime.js +0 -558
- package/src/runtime-pi/xFormData.js +0 -24
- package/src/runtime-pi/xHeaders.js +0 -146
- package/src/runtime-pi/xRequest.js +0 -46
- package/src/runtime-pi/xRequestHeaders.js +0 -109
- package/src/runtime-pi/xResponse.js +0 -33
- package/src/runtime-pi/xResponseHeaders.js +0 -117
- package/src/runtime-pi/xxHttpMessage.js +0 -102
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { WebfloClient } from './WebfloClient.js';
|
|
2
|
+
import { Context } from './Context.js';
|
|
3
|
+
|
|
4
|
+
const { Observer } = webqit;
|
|
5
|
+
|
|
6
|
+
export class WebfloRootClient1 extends WebfloClient {
|
|
7
|
+
|
|
8
|
+
static get Context() { return Context; }
|
|
9
|
+
|
|
10
|
+
static create(host, cx = {}) {
|
|
11
|
+
return new this(host, this.Context.create(cx));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#cx;
|
|
15
|
+
get cx() { return this.#cx; }
|
|
16
|
+
|
|
17
|
+
constructor(host, cx) {
|
|
18
|
+
if (!(host instanceof Document)) {
|
|
19
|
+
throw new Error('Argument #1 must be a Document instance');
|
|
20
|
+
}
|
|
21
|
+
super(host);
|
|
22
|
+
if (!(cx instanceof this.constructor.Context)) {
|
|
23
|
+
throw new Error('Argument #2 must be a Webflo Context instance');
|
|
24
|
+
}
|
|
25
|
+
this.#cx = cx;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
initialize() {
|
|
29
|
+
// Main initializations
|
|
30
|
+
let undoControl = super.initialize();
|
|
31
|
+
// Bind global prompt handlers
|
|
32
|
+
const promptsHandler = (e) => {
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
if (e.defaultPrevented || e.immediatePropagationStopped) return;
|
|
36
|
+
let message = e.data;
|
|
37
|
+
if (e.data?.message) {
|
|
38
|
+
message = e.data.message + (e.data.details ? `\r\n${e.data.details}` : '');
|
|
39
|
+
}
|
|
40
|
+
window.queueMicrotask(() => {
|
|
41
|
+
if (e.type === 'confirm') {
|
|
42
|
+
e.respondWith(confirm(message));
|
|
43
|
+
} else if (e.type === 'prompt') {
|
|
44
|
+
e.respondWith(prompt(message));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}, 10);
|
|
48
|
+
};
|
|
49
|
+
this.backgroundMessaging.handleMessages('confirm', promptsHandler);
|
|
50
|
+
this.backgroundMessaging.handleMessages('prompt', promptsHandler);
|
|
51
|
+
// Respond to background activity request at pageload
|
|
52
|
+
const scope = {};
|
|
53
|
+
if (scope.backgroundMessagingMeta = document.querySelector('meta[name="X-Background-Messaging"]')) {
|
|
54
|
+
scope.backgroundMessaging = this.$createBackgroundMessagingFrom(scope.backgroundMessagingMeta.content);
|
|
55
|
+
this.backgroundMessaging.add(scope.backgroundMessaging);
|
|
56
|
+
}
|
|
57
|
+
if (scope.hydrationData = document.querySelector('script[rel="hydration"][type="application/json"]')) {
|
|
58
|
+
try {
|
|
59
|
+
const hydrationDataJson = JSON.parse((scope.hydrationData.textContent + '').trim());
|
|
60
|
+
const httpEvent = this.constructor.HttpEvent.create(null, { url: this.location.href});
|
|
61
|
+
window.queueMicrotask(() => {
|
|
62
|
+
this.render(httpEvent, hydrationDataJson);
|
|
63
|
+
});
|
|
64
|
+
} catch(e) {}
|
|
65
|
+
}
|
|
66
|
+
// Service Worker && COMM
|
|
67
|
+
if (this.cx.params.service_worker?.filename) {
|
|
68
|
+
const { public_base_url: base, service_worker: { filename, ...restServiceWorkerParams } } = this.cx.params;
|
|
69
|
+
const { vapid_key_env, push_registration_url_env, ..._restServiceWorkerParams } = restServiceWorkerParams;
|
|
70
|
+
const swParams = {
|
|
71
|
+
..._restServiceWorkerParams,
|
|
72
|
+
VAPID_PUBLIC_KEY: this.cx.params.env[vapid_key_env],
|
|
73
|
+
PUSH_REGISTRATION_PUBLIC_URL: this.cx.params.env[push_registration_url_env],
|
|
74
|
+
startMessages: true
|
|
75
|
+
};
|
|
76
|
+
//this.workport.registerServiceWorker(base + filename, swParams);
|
|
77
|
+
}
|
|
78
|
+
if (window.opener) {
|
|
79
|
+
// Window opener pinging
|
|
80
|
+
const $undoControl = undoControl;
|
|
81
|
+
const beforeunloadHandler = () => {
|
|
82
|
+
window.opener.postMessage('close');
|
|
83
|
+
};
|
|
84
|
+
window.addEventListener('beforeunload', beforeunloadHandler);
|
|
85
|
+
undoControl = () => {
|
|
86
|
+
window.removeEventListener('beforeunload', beforeunloadHandler);
|
|
87
|
+
$undoControl();
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return undoControl
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The following methods
|
|
95
|
+
* are not to be inherited
|
|
96
|
+
* by sub classes
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
control() {
|
|
100
|
+
// IMPORTANT: we're calling super.controlClassic()
|
|
101
|
+
const undoControl = super.controlClassic((newHref) => {
|
|
102
|
+
try {
|
|
103
|
+
// Save current scroll position
|
|
104
|
+
this.host.history.replaceState({
|
|
105
|
+
...(this.currentEntry()?.getState?.() || {}),
|
|
106
|
+
scrollPosition: this.host === window.document ? [window.scrollX, window.scrollY] : [this.host.scrollLeft, this.host.scrollTop,],
|
|
107
|
+
}, '', this.location.href);
|
|
108
|
+
} catch (e) { }
|
|
109
|
+
// Do actual location update
|
|
110
|
+
try { this.host.history.pushState({}, '', newHref); } catch (e) { }
|
|
111
|
+
});
|
|
112
|
+
// ONPOPSTATE
|
|
113
|
+
const popstateHandler = (e) => {
|
|
114
|
+
if (this.isHashChange(location)) {
|
|
115
|
+
Observer.set(this.location, 'href', location.href);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Navigation details
|
|
119
|
+
const detail = {
|
|
120
|
+
navigationType: 'traverse',
|
|
121
|
+
navigationOrigins: [],
|
|
122
|
+
destination: this._asEntry(e.state),
|
|
123
|
+
source: this.currentEntry(),
|
|
124
|
+
userInitiated: true,
|
|
125
|
+
};
|
|
126
|
+
// Traversal?
|
|
127
|
+
// Push
|
|
128
|
+
this.navigate(location.href, {}, detail);
|
|
129
|
+
};
|
|
130
|
+
window.addEventListener('popstate', popstateHandler);
|
|
131
|
+
return () => {
|
|
132
|
+
this.host.removeEventListener('popstate', popstateHandler);
|
|
133
|
+
undoControl();
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
reload() {
|
|
138
|
+
return window.history.reload();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
back() {
|
|
142
|
+
return window.history.back();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
forward() {
|
|
146
|
+
return window.history.forward();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
traverseTo(...args) {
|
|
150
|
+
return window.history.go(...args);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
entries() {
|
|
154
|
+
return window.history;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
currentEntry() {
|
|
158
|
+
return this._asEntry(history.state);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async updateCurrentEntry(params, url = null) {
|
|
162
|
+
window.history.replaceState(params.state, '', url);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async push(url, state = {}) {
|
|
166
|
+
if (typeof url === 'string' && url.startsWith('&')) { url = this.location.href.split('#')[0] + (this.location.href.includes('?') ? url : url.replace('&', '?')); }
|
|
167
|
+
url = new URL(url, this.location.href);
|
|
168
|
+
window.history.pushState(state, '', url.href);
|
|
169
|
+
Observer.set(this.location, 'href', url.href);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async applyPostRenderState(httpEvent) {
|
|
173
|
+
const destinationState = httpEvent.detail.destination?.getState() || {};
|
|
174
|
+
if (destinationState.scrollPosition?.length) {
|
|
175
|
+
window.scroll(...destinationState.scrollPosition);
|
|
176
|
+
(document.querySelector('[autofocus]') || document.body).focus();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { WebfloRootClient1 } from './WebfloRootClient1.js';
|
|
2
|
+
|
|
3
|
+
const { Observer } = webqit;
|
|
4
|
+
|
|
5
|
+
export class WebfloRootClient2 extends WebfloRootClient1 {
|
|
6
|
+
|
|
7
|
+
control() {
|
|
8
|
+
// Detect source elements
|
|
9
|
+
let navigationOrigins = [];
|
|
10
|
+
// Capture all link-clicks
|
|
11
|
+
const clickHandler = (e) => {
|
|
12
|
+
if (!this._canIntercept(e)) return;
|
|
13
|
+
let anchorEl = e.target.closest('a');
|
|
14
|
+
if (!anchorEl || !anchorEl.href || anchorEl.target) return;
|
|
15
|
+
navigationOrigins = [anchorEl, null, anchorEl.closest('[navigationcontext]')];
|
|
16
|
+
};
|
|
17
|
+
// Capture all form-submits
|
|
18
|
+
const submitHandler = (e) => {
|
|
19
|
+
if (!this._canIntercept(e)) return;
|
|
20
|
+
navigationOrigins = [e.submitter, e.target.closest('form'), e.target.closest('[navigationcontext]')];
|
|
21
|
+
};
|
|
22
|
+
// Handle navigation event which happens after the above
|
|
23
|
+
const navigateHandler = (e) => {
|
|
24
|
+
if (!e.canIntercept || e.downloadRequest !== null) return;
|
|
25
|
+
if (e.hashChange) {
|
|
26
|
+
Observer.set(this.location, 'href', e.destination.url);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const { navigationType, destination, signal, formData, info, userInitiated } = e;
|
|
30
|
+
if (formData && navigationOrigins[1]?.hasAttribute('webflo-no-intercept')) return;
|
|
31
|
+
if (formData && (navigationOrigins[0] || {}).name) { formData.set(navigationOrigins[0].name, navigationOrigins[0].value); }
|
|
32
|
+
// Navigation details
|
|
33
|
+
const detail = {
|
|
34
|
+
navigationType,
|
|
35
|
+
navigationOrigins,
|
|
36
|
+
destination,
|
|
37
|
+
source: this.currentEntry(),
|
|
38
|
+
userInitiated,
|
|
39
|
+
info
|
|
40
|
+
};
|
|
41
|
+
navigationOrigins = [];
|
|
42
|
+
// Traversal?
|
|
43
|
+
// Push
|
|
44
|
+
const url = new URL(destination.url, this.location.href);
|
|
45
|
+
const init = {
|
|
46
|
+
method: formData && 'POST' || 'GET',
|
|
47
|
+
body: formData,
|
|
48
|
+
signal
|
|
49
|
+
};
|
|
50
|
+
this.updateCurrentEntry({
|
|
51
|
+
state: {
|
|
52
|
+
...(this.currentEntry().getState() || {}),
|
|
53
|
+
scrollPosition: [window.scrollX, window.scrollY],
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const runtime = this;
|
|
57
|
+
e.intercept({
|
|
58
|
+
scroll: 'after-transition',
|
|
59
|
+
focusReset: 'after-transition',
|
|
60
|
+
async handler() { await runtime.navigate(url, init, detail); },
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
window.addEventListener('click', clickHandler);
|
|
64
|
+
window.addEventListener('submit', submitHandler);
|
|
65
|
+
window.navigation.addEventListener('navigate', navigateHandler);
|
|
66
|
+
return () => {
|
|
67
|
+
this.host.removeEventListener('click', clickHandler);
|
|
68
|
+
this.host.removeEventListener('submit', submitHandler);
|
|
69
|
+
window.navigation.removeEventListener('navigate', navigateHandler);
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
reload(params) {
|
|
74
|
+
return window.navigation.reload(params);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
back() {
|
|
78
|
+
return window.navigation.canGoBack && window.navigation.back();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
forward() {
|
|
82
|
+
return window.navigation.canGoForward && window.navigation.forward();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
traverseTo(...args) {
|
|
86
|
+
return window.navigation.traverseTo(...args);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
entries() {
|
|
90
|
+
return window.navigation.entries();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
currentEntry() {
|
|
94
|
+
return window.navigation.currentEntry;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async updateCurrentEntry(params, url = null) {
|
|
98
|
+
if (!url || url === window.navigation.currentEntry.url) {
|
|
99
|
+
window.navigation.updateCurrentEntry(params);
|
|
100
|
+
} else { await window.navigation.navigate(url, { ...params, history: 'replace' }).committed; }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async push(url, state = {}) {
|
|
104
|
+
if (typeof url === 'string' && url.startsWith('&')) { url = this.location.href.split('#')[0] + (this.location.href.includes('?') ? url : url.replace('&', '?')); }
|
|
105
|
+
url = new URL(url, this.location.href);
|
|
106
|
+
await window.navigation.navigate(url.href, state).committed;
|
|
107
|
+
Observer.set(this.location, 'href', url.href);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { WebfloClient } from './WebfloClient.js';
|
|
2
|
+
import { Url } from './Url.js';
|
|
3
|
+
|
|
4
|
+
const { Observer } = webqit;
|
|
5
|
+
|
|
6
|
+
export class WebfloSubClient extends WebfloClient {
|
|
7
|
+
|
|
8
|
+
static defineElement() {
|
|
9
|
+
const embedTagNames = 'webflo-embedded';
|
|
10
|
+
window.customElements.define(embedTagNames, class extends HTMLElement {
|
|
11
|
+
|
|
12
|
+
#superRuntime;
|
|
13
|
+
#webfloControllerUninitialize;
|
|
14
|
+
#location;
|
|
15
|
+
#reflectAction;
|
|
16
|
+
|
|
17
|
+
static get observedAttributes() { return ['location']; }
|
|
18
|
+
|
|
19
|
+
get startupFlight() {
|
|
20
|
+
return this.hasAttribute('location');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get location() {
|
|
24
|
+
if (!this.#location) {
|
|
25
|
+
this.#location = new URL(this.getAttribute('location') || '', window.location.origin);
|
|
26
|
+
}
|
|
27
|
+
return this.#location;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set location(value) {
|
|
31
|
+
if (!(value instanceof URL)) {
|
|
32
|
+
value = new URL(value, window.location.origin);
|
|
33
|
+
}
|
|
34
|
+
if (value.href === this.location.href) return;
|
|
35
|
+
this.#location = value;
|
|
36
|
+
this.setAttribute('location', value.href.replace(value.origin, ''));
|
|
37
|
+
if (!this.#reflectAction) {
|
|
38
|
+
this.webfloRuntime.navigate(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
reflectLocation(location) {
|
|
43
|
+
this.#reflectAction = true;
|
|
44
|
+
this.location = location;
|
|
45
|
+
this.#reflectAction = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
49
|
+
if (oldValue === newValue) return;
|
|
50
|
+
this.location = newValue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
connectedCallback() {
|
|
54
|
+
this.#superRuntime = (this.parentNode?.closest(embedTagNames) || document).webfloRuntime;
|
|
55
|
+
this.#webfloControllerUninitialize = WebfloSubClient.create(this, this.#superRuntime).initialize();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
disconnectedCallback() {
|
|
59
|
+
this.#webfloControllerUninitialize();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static create(host, superRuntime) {
|
|
65
|
+
return new this(host, superRuntime);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#superRuntime;
|
|
69
|
+
get superRuntime() { return this.#superRuntime; }
|
|
70
|
+
|
|
71
|
+
get cx() { return this.#superRuntime.cx; }
|
|
72
|
+
|
|
73
|
+
get workport() { return this.#superRuntime.workport; }
|
|
74
|
+
|
|
75
|
+
constructor(host, superRuntime) {
|
|
76
|
+
if (!(host instanceof HTMLElement)) {
|
|
77
|
+
throw new Error('Argument #1 must be a HTMLElement instance');
|
|
78
|
+
}
|
|
79
|
+
super(host);
|
|
80
|
+
if (!(superRuntime instanceof WebfloClient)) {
|
|
81
|
+
throw new Error('Argument #2 must be a Webflo Client instance');
|
|
82
|
+
}
|
|
83
|
+
this.#superRuntime = superRuntime;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
initialize() {
|
|
87
|
+
if (this.host.location.origin !== window.location.origin) {
|
|
88
|
+
throw new Error(`Webflo embeddable origin violation in "${window.location}"`);
|
|
89
|
+
}
|
|
90
|
+
const uncontrols = super.initialize();
|
|
91
|
+
this.backgroundMessaging.setParent(this.#superRuntime.backgroundMessaging);
|
|
92
|
+
this.navigate(this.location.href);
|
|
93
|
+
return () => {
|
|
94
|
+
if (this.backgroundMessaging.parentNode === this.#superRuntime.backgroundMessaging) {
|
|
95
|
+
this.backgroundMessaging.setParent(null);
|
|
96
|
+
}
|
|
97
|
+
uncontrols();
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
control() {
|
|
102
|
+
return super.controlClassic((newHref) => {
|
|
103
|
+
this.host.reflectLocation(newHref);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
reload(params) {
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
back() {
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
forward() {
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
traverseTo(...args) {
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
entries() {
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
currentEntry() {
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async updateCurrentEntry(params, url = null) {
|
|
126
|
+
this.host.reflectLocation(url);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async push(url, state = {}) {
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
hardRedirect(location, backgroundMessaging = null) {
|
|
133
|
+
location = typeof location === 'string' ? new URL(location, this.location.origin) : location;
|
|
134
|
+
const width = Math.min(800, window.innerWidth);
|
|
135
|
+
const height = Math.min(600, window.innerHeight);
|
|
136
|
+
const left = (window.outerWidth - width) / 2;
|
|
137
|
+
const top = (window.outerHeight - height) / 2;
|
|
138
|
+
const popup = window.open(location, '_blank', `popup=true,width=${width},height=${height},left=${left},top=${top}`);
|
|
139
|
+
if (backgroundMessaging) {
|
|
140
|
+
backgroundMessaging.postMessage('keepAlive');
|
|
141
|
+
Observer.set(this.navigator, 'redirecting', new Url/*NOT URL*/(location), { diff: true });
|
|
142
|
+
backgroundMessaging.addEventListener('close', (e) => {
|
|
143
|
+
Observer.set(this.navigator, 'redirecting', null);
|
|
144
|
+
popup.postMessage('timeout:5');
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
popup.close();
|
|
147
|
+
}, 5000);
|
|
148
|
+
});
|
|
149
|
+
window.addEventListener('message', (e) => {
|
|
150
|
+
if (e.source === popup && e.data === 'close') {
|
|
151
|
+
backgroundMessaging.close();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async applyPostRenderState(httpEvent) {
|
|
158
|
+
if (httpEvent.url.hash) {
|
|
159
|
+
this.host.querySelector(httpEvent.url.hash)?.scrollIntoView();
|
|
160
|
+
} else {
|
|
161
|
+
this.host.scrollTo(0, 0);
|
|
162
|
+
}
|
|
163
|
+
(this.host.querySelector('[autofocus]') || this.host).focus();
|
|
164
|
+
}
|
|
165
|
+
}
|