Skip to content
Merged
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
86 changes: 57 additions & 29 deletions src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { tryExecute } from '@umbraco-cms/backoffice/resources';

Check notice on line 1 in src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (release/17.0)

✅ No longer an issue: Overall Code Complexity

The mean cyclomatic complexity in this module is no longer above the threshold
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbBooleanState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
Expand All @@ -7,6 +7,9 @@
import { UmbDocumentPreviewRepository } from '@umbraco-cms/backoffice/document';
import { UMB_SERVER_CONTEXT } from '@umbraco-cms/backoffice/server';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { HubConnectionBuilder, type HubConnection } from '@umbraco-cms/backoffice/external/signalr';
import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification';
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';

const UMB_LOCALSTORAGE_SESSION_KEY = 'umb:previewSessions';

Expand All @@ -31,7 +34,7 @@
#culture?: string | null;
#segment?: string | null;
#serverUrl: string = '';
#webSocket?: WebSocket;
#connection?: HubConnection;

#iframeReady = new UmbBooleanState(false);
public readonly iframeReady = this.#iframeReady.asObservable();
Expand All @@ -41,12 +44,13 @@

#documentPreviewRepository = new UmbDocumentPreviewRepository(this);

#notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE;
#localize = new UmbLocalizationController(this);

constructor(host: UmbControllerHost) {
super(host, UMB_PREVIEW_CONTEXT);

this.consumeContext(UMB_SERVER_CONTEXT, (instance) => {
this.#serverUrl = instance?.getServerUrl() ?? '';

const params = new URLSearchParams(window.location.search);

this.#unique = params.get('id');
Expand All @@ -58,37 +62,62 @@
return;
}

this.#setPreviewUrl();
});
}
const serverUrl = instance?.getServerUrl();

#configureWebSocket() {
if (this.#webSocket && this.#webSocket.readyState < 2) return;
if (!serverUrl) {
console.error('No server URL found in context');
return;
}

const url = `${this.#serverUrl.replace('https://', 'wss://')}/umbraco/PreviewHub`;
this.#serverUrl = serverUrl;

this.#webSocket = new WebSocket(url);
this.#setPreviewUrl({ serverUrl });

this.#webSocket.addEventListener('open', () => {
// NOTE: SignalR protocol handshake; it requires a terminating control character.
const endChar = String.fromCharCode(30);
this.#webSocket?.send(`{"protocol":"json","version":1}${endChar}`);
this.#initHubConnection(serverUrl);
});

this.#webSocket.addEventListener('message', (event: MessageEvent<string>) => {
if (!event?.data) return;
this.consumeContext(UMB_NOTIFICATION_CONTEXT, (instance) => {
this.#notificationContext = instance;
});
}

// NOTE: Strip the terminating control character, (from SignalR).
const data = event.data.substring(0, event.data.length - 1);
const json = JSON.parse(data) as { type: number; target: string; arguments: Array<string> };
async #initHubConnection(serverUrl: string) {
const previewHubUrl = `${serverUrl}/umbraco/PreviewHub`;

if (json.type === 1 && json.target === 'refreshed') {
const pageId = json.arguments?.[0];
if (pageId === this.#unique) {
this.#setPreviewUrl({ rnd: Math.random() });
}
// Make sure that no previous connection exists.
if (this.#connection) {
await this.#connection.stop();
this.#connection = undefined;
}

this.#connection = new HubConnectionBuilder().withUrl(previewHubUrl).build();

this.#connection.on('refreshed', (payload) => {
if (payload === this.#unique) {
this.#setPreviewUrl({ rnd: Math.random() });
}
});

this.#connection.onclose(() => {
this.#notificationContext?.peek('warning', {
data: {
headline: this.#localize.term('general_preview'),
message: this.#localize.term('preview_connectionLost'),
},
});
});

try {
await this.#connection.start();
} catch (error) {
console.error('The SignalR connection could not be established', error);
this.#notificationContext?.peek('warning', {
data: {
headline: this.#localize.term('general_preview'),
message: this.#localize.term('preview_connectionFailed'),
},
});
}

Check notice on line 120 in src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (release/17.0)

✅ No longer an issue: Complex Method

UmbPreviewContext.configureWebSocket is no longer above the threshold for cyclomatic complexity. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
}

async #getPublishedUrl(): Promise<string | null> {
Expand Down Expand Up @@ -144,7 +173,7 @@
params.delete(segmentParam);
}

const previewUrl = new URL(url.pathname + '?' + params.toString(), host);
const previewUrl = new URL(`${url.pathname}?${params.toString()}`, host);
const previewUrlString = previewUrl.toString();

this.#previewUrl.setValue(previewUrlString);
Expand Down Expand Up @@ -180,9 +209,9 @@
await this.#documentPreviewRepository.exit();
}

if (this.#webSocket) {
this.#webSocket.close();
this.#webSocket = undefined;
if (this.#connection) {
await this.#connection.stop();
this.#connection = undefined;
}

let url = await this.#getPublishedUrl();
Expand All @@ -202,7 +231,6 @@

iframeLoaded(iframe: HTMLIFrameElement) {
if (!iframe) return;
this.#configureWebSocket();
this.#iframeReady.setValue(true);
}

Expand Down
5 changes: 4 additions & 1 deletion src/Umbraco.Web.UI.Client/src/assets/lang/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2602,13 +2602,16 @@ export default {
returnToPreviewHeadline: 'Forhåndsvisning af indholdet?',
returnToPreviewDescription:
'Du har afslutet forhåndsvisning, vil du starte forhåndsvisning igen for at\n se seneste gemte version af indholdet?\n ',
returnToPreviewAcceptButton: 'Start forhåndsvisning igen',
returnToPreviewDeclineButton: 'Se udgivet indhold',
viewPublishedContentHeadline: 'Se udgivet indhold?',
viewPublishedContentDescription:
'Du er i forhåndsvisning, vil du afslutte for at se den udgivet\n version?\n ',
viewPublishedContentAcceptButton: 'Se udgivet version',
viewPublishedContentDeclineButton: 'Forbliv i forhåndsvisning',
returnToPreviewAcceptButton: 'Preview latest version',
connectionFailed:
'Kunne ikke etablere forbindelse til serveren, forhåndsvisning af liveopdateringer vil ikke fungere.',
connectionLost: 'Forbindelse til serveren mistet, forhåndsvisning af liveopdateringer vil ikke fungere.',
},
permissions: {
FolderCreation: 'Mappeoprettelse',
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2748,6 +2748,8 @@ export default {
'You are in Preview Mode, do you want exit in order to view the published version of your website?',
viewPublishedContentAcceptButton: 'View published version',
viewPublishedContentDeclineButton: 'Stay in preview mode',
connectionFailed: 'Could not establish a connection to the server, preview live updates will not work.',
connectionLost: 'Connection to the server lost, preview live updates will not work.',
},
permissions: {
FolderCreation: 'Folder creation',
Expand Down
Loading