Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {

rejoiningAnimation: HTMLDivElement;

reloadButton: HTMLButtonElement;
retryButton: HTMLButtonElement;

resumeButton: HTMLButtonElement;

status: HTMLParagraphElement;

reconnect = true;
operation: ReconnectDisplayUpdateOptions['type'] = 'reconnect';

remote = false;

Expand Down Expand Up @@ -65,10 +65,10 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
this.status = document.createElement('p');
this.status.innerHTML = '';

this.reloadButton = document.createElement('button');
this.reloadButton.style.display = 'none';
this.reloadButton.innerHTML = 'Retry';
this.reloadButton.addEventListener('click', this.retry.bind(this));
this.retryButton = document.createElement('button');
this.retryButton.style.display = 'none';
this.retryButton.innerHTML = 'Retry';
this.retryButton.addEventListener('click', this.retry.bind(this));

this.resumeButton = document.createElement('button');
this.resumeButton.style.display = 'none';
Expand All @@ -77,7 +77,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {

this.dialog.appendChild(this.rejoiningAnimation);
this.dialog.appendChild(this.status);
this.dialog.appendChild(this.reloadButton);
this.dialog.appendChild(this.retryButton);
this.dialog.appendChild(this.resumeButton);

this.overlay.appendChild(this.dialog);
Expand All @@ -94,30 +94,33 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
this.document.body.appendChild(this.host);
}

this.reconnect = options?.type === 'reconnect';
this.operation = options?.type ?? 'reconnect';
this.remote = options?.type === 'pause' ? options?.remote : false;

this.reloadButton.style.display = 'none';
this.retryButton.style.display = 'none';
this.rejoiningAnimation.style.display = 'block';
this.status.innerHTML = 'Rejoining the server...';
this.host.style.display = 'block';
this.overlay.classList.add(DefaultReconnectDisplay.ReconnectVisibleClassName);
}

update(options: ReconnectDisplayUpdateOptions): void {
this.reconnect = options.type === 'reconnect';
if (this.reconnect) {
this.operation = options.type;
this.remote = options?.type === 'pause' ? options?.remote : false;

if (this.operation === 'pause') {
this.retryButton.style.display = 'none';
this.rejoiningAnimation.style.display = 'none';
this.status.innerHTML = 'The session has been paused by the server.';
this.resumeButton.style.display = 'block';
} else {
const { currentAttempt, secondsToNextAttempt } = options as ReconnectOptions;
if (currentAttempt === 1 || secondsToNextAttempt === 0) {
this.status.innerHTML = 'Rejoining the server...';
} else {
const unitText = secondsToNextAttempt === 1 ? 'second' : 'seconds';
this.status.innerHTML = `Rejoin failed... trying again in ${secondsToNextAttempt} ${unitText}`;
}
} else {
this.reloadButton.style.display = 'none';
this.rejoiningAnimation.style.display = 'none';
this.status.innerHTML = 'The session has been paused by the server.';
this.resumeButton.style.display = 'block';
}
}

Expand All @@ -128,14 +131,23 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {

failed(): void {
this.rejoiningAnimation.style.display = 'none';
if (this.reconnect) {
this.reloadButton.style.display = 'block';
if (this.operation === 'pause') {
// Failed to resume from pause.
if (this.remote) {
// Circuit failed to resume after an ungraceful pause (e.g., server restart).
// We treat this as non-recoverable rejection.
this.rejected();
} else {
// Circuit failed to resume after a graceful (client-requested) pause.
// We show a retry UI to allow the user to try to continue without losing the state.
this.resumeButton.style.display = 'block';
this.status.innerHTML = 'Failed to resume.<br />Please retry or reload the page.';
}
} else {
// Failed to reconnect.
this.retryButton.style.display = 'block';
this.status.innerHTML = 'Failed to rejoin.<br />Please retry or reload the page.';
this.document.addEventListener('visibilitychange', this.retryWhenDocumentBecomesVisible);
} else {
this.status.innerHTML = 'Failed to resume the session.<br />Please reload the page.';
this.resumeButton.style.display = 'none';
this.reloadButton.style.display = 'none';
}
}

Expand All @@ -160,7 +172,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
this.update({ type: 'pause', remote: this.remote });
const resumeSuccessful = await Blazor.resumeCircuit!();
if (!resumeSuccessful) {
this.rejected();
this.failed();
}
}
} catch (err: unknown) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
<p class="components-pause-visible">
The session has been paused by the server.
</p>
<button id="components-resume-button" class="components-pause-visible">
Resume
</button>
<p class="components-resume-failed-visible">
Failed to resume the session.<br />Please reload the page.
Failed to resume the session.<br />Please retry or reload the page.
</p>
<button id="components-resume-button" class="components-pause-visible components-resume-failed-visible">
Resume
</button>
</div>
</dialog>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function handleReconnectStateChanged(event) {
reconnectModal.close();
} else if (event.detail.state === "failed") {
document.addEventListener("visibilitychange", retryWhenDocumentBecomesVisible);
} else if (event.detail.state === "rejected") {
} else if (event.detail.state === "rejected" || (event.detail.state === "resume-failed" && event.detail.remote)) {
location.reload();
}
}
Expand Down
Loading