Skip to content

Commit 688acde

Browse files
committed
Fix SPA navigation issues
1 parent bb46cb8 commit 688acde

File tree

3 files changed

+33
-26
lines changed

3 files changed

+33
-26
lines changed

src/runtime-pi/webflo-client/WebfloClient.js

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,17 @@ export class WebfloClient extends WebfloRuntime {
322322
method: null
323323
});
324324
};
325+
325326
// Ping existing background processes
326327
// !IMPORTANT: Posting to the group when empty will keep the event until next addition
327328
// and we don't want that
328329
if (this.#background.length) {
329330
const url = { ...Url.copy(scopeObj.url), method: scopeObj.request.method };
330331
this.#background.postMessage(url, { wqEventOptions: { type: 'navigate' } });
331332
}
333+
334+
console.log('_______,', scopeObj.detail.navigationType);
335+
332336
// Dispatch for response
333337
scopeObj.response = await this.dispatchNavigationEvent({
334338
httpEvent: scopeObj.httpEvent,
@@ -342,20 +346,15 @@ export class WebfloClient extends WebfloRuntime {
342346
clientPortB: wqMessageChannel.port2,
343347
originalRequestInit: scopeObj.init
344348
});
349+
345350
// Decode response
346351
scopeObj.finalUrl = scopeObj.response.url || scopeObj.request.url;
347352
if (scopeObj.response.redirected || scopeObj.detail.navigationType === 'rdr' || scopeObj.detail.isHoisted) {
348353
const stateData = { ...(this.currentEntry()?.getState() || {}), redirected: true, };
349354
await this.updateCurrentEntry({ state: stateData }, scopeObj.finalUrl);
350355
}
356+
351357
// Transition UI
352-
Observer.set(this.transition.from, Url.copy(this.location));
353-
Observer.set(this.transition.to, 'href', scopeObj.finalUrl);
354-
Observer.set(this.transition, 'rel', this.transition.from.pathname === this.transition.to.pathname ? 'unchanged' : (
355-
`${this.transition.from.pathname}/`.startsWith(`${this.transition.to.pathname}/`) ? 'parent' : (
356-
`${this.transition.to.pathname}/`.startsWith(`${this.transition.from.pathname}/`) ? 'child' : 'unrelated'
357-
)
358-
));
359358
await this.transitionUI(async () => {
360359
// Set post-request states
361360
Observer.set(this.location, 'href', scopeObj.finalUrl);
@@ -374,12 +373,12 @@ export class WebfloClient extends WebfloRuntime {
374373
!(['GET'].includes(scopeObj.request.method) || scopeObj.response.redirected || scopeObj.detail.navigationType === 'rdr')
375374
);
376375
await this.applyPostRenderState(scopeObj.httpEvent);
377-
});
376+
}, scopeObj.finalUrl, scopeObj.detail);
378377
}
379378

380379
async dispatchNavigationEvent({ httpEvent, crossLayerFetch, clientPortB, originalRequestInit, processObj = {} }) {
381380
let response = await super.dispatchNavigationEvent({ httpEvent, crossLayerFetch, clientPortB });
382-
381+
383382
// Extract interactive. mode handling
384383
const handleInteractiveMode = async (resolve) => {
385384
const liveResponse = await LiveResponse.from(response);
@@ -469,19 +468,29 @@ export class WebfloClient extends WebfloRuntime {
469468
return 2; // Window reload
470469
}
471470

472-
async transitionUI(updateCallback) {
473-
if (document.startViewTransition && this.withViewTransitions) {
471+
async transitionUI(updateCallback, finalUrl, detail) {
472+
// Set initial states
473+
Observer.set(this.transition.from, Url.copy(this.location));
474+
Observer.set(this.transition.to, 'href', finalUrl);
475+
const viewTransitionRel = this.transition.from.pathname === this.transition.to.pathname ? 'same' : (
476+
`${this.transition.from.pathname}/`.startsWith(`${this.transition.to.pathname}/`) ? 'out' : (
477+
`${this.transition.to.pathname}/`.startsWith(`${this.transition.from.pathname}/`) ? 'in' : 'other'
478+
)
479+
);
480+
Observer.set(this.transition, 'rel', viewTransitionRel);
481+
// Trigger transition
482+
if (document.startViewTransition && this.withViewTransitions && !detail.hasUAVisualTransition) {
474483
const synthesizeWhile = window.webqit?.realdom?.synthesizeWhile || ((callback) => callback());
475484
return new Promise(async (resolve) => {
476485
await synthesizeWhile(async () => {
477-
Observer.set(this.transition, 'phase', 1);
478-
const viewTransition = document.startViewTransition(updateCallback);
486+
Observer.set(this.transition, 'phase', 'old');
487+
const viewTransition = document.startViewTransition({ update: updateCallback, styles: ['navigation', viewTransitionRel] });
479488
try { await viewTransition.updateCallbackDone; } catch (e) { console.log(e); }
480-
Observer.set(this.transition, 'phase', 2);
489+
Observer.set(this.transition, 'phase', 'new');
481490
try { await viewTransition.ready; } catch (e) { console.log(e); }
482-
Observer.set(this.transition, 'phase', 3);
491+
Observer.set(this.transition, 'phase', 'start');
483492
try { await viewTransition.finished; } catch (e) { console.log(e); }
484-
Observer.set(this.transition, 'phase', 0);
493+
Observer.set(this.transition, 'phase', 'end');
485494
resolve();
486495
});
487496
});

src/runtime-pi/webflo-client/WebfloRootClient2.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,16 @@ export class WebfloRootClient2 extends WebfloRootClient1 {
2424
if (!e.canIntercept
2525
|| e.downloadRequest !== null
2626
|| !this.isSpaRoute(e.destination.url)
27-
|| e.navigationType === 'reload') return;
27+
|| ['reload'].includes(e.navigationType)) return;
2828
if (e.hashChange) {
2929
Observer.set(this.location, 'href', e.destination.url);
3030
return;
3131
}
32-
const { navigationType, destination, signal, formData, info, userInitiated } = e;
32+
if (e.navigationType === 'replace') {
33+
e.intercept({});
34+
return;
35+
}
36+
const { navigationType, destination, signal, formData, info, userInitiated, hasUAVisualTransition } = e;
3337
if (formData && navigationOrigins[1]?.hasAttribute('webflo-no-intercept')) return;
3438
if (formData && (navigationOrigins[0] || {}).name) { formData.set(navigationOrigins[0].name, navigationOrigins[0].value); }
3539
// Navigation details
@@ -39,6 +43,7 @@ export class WebfloRootClient2 extends WebfloRootClient1 {
3943
destination,
4044
source: this.currentEntry(),
4145
userInitiated,
46+
hasUAVisualTransition,
4247
info
4348
};
4449
navigationOrigins = [];
@@ -50,18 +55,11 @@ export class WebfloRootClient2 extends WebfloRootClient1 {
5055
body: formData,
5156
//signal TODO: auto-aborts on a redirect response which thus fails to parse
5257
};
53-
this.updateCurrentEntry({
54-
state: {
55-
...(this.currentEntry().getState() || {}),
56-
scrollPosition: [window.scrollX, window.scrollY],
57-
}
58-
});
5958
const runtime = this;
6059
e.intercept({
6160
scroll: 'after-transition',
6261
focusReset: 'after-transition',
6362
async handler() {
64-
if (navigationType === 'replace') return;
6563
await runtime.navigate(url, init, detail);
6664
},
6765
});

src/runtime-pi/webflo-client/WebfloSubClient.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class WebfloSubClient extends WebfloClient {
100100
if (response && LiveResponse.hasBackground(response)) {
101101
Observer.set(this.navigator, 'redirecting', new Url/*NOT URL*/(location), { diff: true });
102102
const backgroundPort = LiveResponse.getBackground(response);
103-
backgroundPort.postMessage('keep-alive');
103+
backgroundPort.postMessage(true, { wqEventOptions: { type: 'keep-alive' } });
104104
backgroundPort.addEventListener('close', (e) => {
105105
window.removeEventListener('message', windowMessageHandler);
106106
Observer.set(this.navigator, 'redirecting', null);

0 commit comments

Comments
 (0)