-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpostMessageEvent.hooks.ts
More file actions
188 lines (174 loc) · 7.66 KB
/
postMessageEvent.hooks.ts
File metadata and controls
188 lines (174 loc) · 7.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import { isOpeningInNewTab } from "../../common/inIframe";
import Config, { setConfigFromParams } from "../../configManager/configManager";
import { PublicLogger } from "../../logger/logger";
import { ILivePreviewWindowType } from "../../types/types";
import { addParamsToUrl, isOpeningInTimeline } from "../../utils";
import livePreviewPostMessage from "./livePreviewEventManager";
import { LIVE_PREVIEW_POST_MESSAGE_EVENTS } from "./livePreviewEventManager.constant";
import {
HistoryLivePreviewPostMessageEventData,
LivePreviewInitEventResponse,
OnChangeLivePreviewPostMessageEventData,
OnChangeLivePreviewPostMessageEventTypes,
} from "./types/livePreviewPostMessageEvent.type";
/**
* Registers a post message event listener for history-related events.
* The listener handles events for forward, backward, and reload actions on the browser history.
*/
export function useHistoryPostMessageEvent(): void {
livePreviewPostMessage?.on<HistoryLivePreviewPostMessageEventData>(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY,
(event) => {
switch (event.data.type) {
case "forward": {
window.history.forward();
break;
}
case "backward": {
window.history.back();
break;
}
case "reload": {
window.history.go();
break;
}
default: {
const exhaustiveCheck: never = event.data.type;
throw new Error(`Unhandled event: ${exhaustiveCheck}`);
}
}
}
);
}
/**
* Registers a post message event listener for updating the entry in the live preview.
*/
export function useOnEntryUpdatePostMessageEvent(): void {
livePreviewPostMessage?.on<OnChangeLivePreviewPostMessageEventData>(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.ON_CHANGE,
(event) => {
try {
const { ssr, onChange, stackDetails } = Config.get();
const event_type = event.data._metadata?.event_type;
setConfigFromParams({
live_preview: event.data.hash,
});
// This section will run when there is a change in the entry and the website is CSR
if (!ssr && !event_type) {
onChange();
}
if (isOpeningInNewTab()) {
if (!window) {
PublicLogger.error("window is not defined");
return;
};
if (ssr && !event_type) {
const url = new URL(window.location.href);
let live_preview = url.searchParams.get("live_preview");
let content_type_uid = url.searchParams.get("content_type_uid");
let entry_uid = url.searchParams.get("entry_uid");
if (live_preview && content_type_uid && entry_uid) {
// All required params are present, just reload
window.location.reload();
} else {
live_preview = event.data.hash;
content_type_uid = event.data.content_type_uid || stackDetails.$contentTypeUid?.toString() || "";
entry_uid = event.data.entry_uid || stackDetails.$entryUid?.toString() || "";
// Set missing params and redirect
url.searchParams.set("live_preview", live_preview);
if (content_type_uid) {
url.searchParams.set(
"content_type_uid",
content_type_uid
);
}
if (entry_uid) {
url.searchParams.set(
"entry_uid",
entry_uid
);
}
window.location.href = url.toString();
}
}
// This section will run when the hash changes and the website is SSR or CSR
if (event_type === OnChangeLivePreviewPostMessageEventTypes.HASH_CHANGE) {
const newUrl = new URL(window.location.href);
newUrl.searchParams.set("live_preview", event.data.hash);
window.history.pushState({}, "", newUrl.toString());
}
// This section will run when the URL of the page changes
if (event_type === OnChangeLivePreviewPostMessageEventTypes.URL_CHANGE && event.data.url) {
window.location.href = event.data.url;
}
}
} catch (error) {
PublicLogger.error("Error handling live preview update:", error);
return;
}
}
);
}
export function sendInitializeLivePreviewPostMessageEvent(): void {
livePreviewPostMessage
?.send<LivePreviewInitEventResponse>(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.INIT,
{
config: {
shouldReload: Config.get().ssr,
href: window.location.href,
sdkVersion: process?.env?.PACKAGE_VERSION,
mode: Config.get().mode,
},
}
)
.then((data) => {
const {
contentTypeUid,
entryUid,
windowType = ILivePreviewWindowType.PREVIEW,
} = data || {};
// TODO: This is a fix for the issue where we were calling sending init in the builder
// Let's remove this condition when we fix it.
if (Config?.get()?.windowType && Config.get().windowType === ILivePreviewWindowType.BUILDER) {
return;
}
if (contentTypeUid && entryUid) {
// TODO: we should not use this function. Instead we should have sideEffect run automatically when we set the config.
setConfigFromParams({
content_type_uid: contentTypeUid,
entry_uid: entryUid,
});
} else {
// TODO: add debug logs that runs conditionally
// PublicLogger.debug(
// "init message did not contain contentTypeUid or entryUid."
// );
}
if (Config.get().ssr || isOpeningInTimeline() || isOpeningInNewTab()) {
addParamsToUrl();
}
Config.set("windowType", windowType);
// set timeout for client side (use to show warning: You are not editing this page)
if (!Config.get().ssr) {
setInterval(() => {
sendCurrentPageUrlPostMessageEvent();
}, 1500);
}
useHistoryPostMessageEvent();
useOnEntryUpdatePostMessageEvent();
})
.catch((e) => {
// TODO: add debug logs that runs conditionally
// PublicLogger.debug("Error while sending init message", e);
});
}
function sendCurrentPageUrlPostMessageEvent(): void {
livePreviewPostMessage
?.send(LIVE_PREVIEW_POST_MESSAGE_EVENTS.CHECK_ENTRY_PAGE, {
href: window.location.href,
})
.catch(() => {
// TODO: add debug logs that runs conditionally
});
}