@nitrogenbuilder/client-php
Version:
Nitrogen Builder PHP Client
215 lines (178 loc) • 5.75 kB
text/typescript
import type { RequestedPageData } from '@nitrogenbuilder/types/socket-server';
import type * as nitrogenTypes from '@nitrogenbuilder/types';
// USED IN CLIENT SIDE PHP apps
declare global {
interface Window {
/**
* This type is available within the client, not the editor or server.
*/
nitrogenPHPClient?: {
pageRequestURL?: string;
pageId?: string | number;
}
}
}
// Host, token come from window.location
type Params = Omit<RequestedPageData, 'id' | 'host' | 'token'>;
// TODO: This should change depending on what we are editing in nitrogen (page, header, footer, etc.)
const nitrogenLocation = 'page';
function init(requestedData: Params) {
// if we are not in builder return and use the data passed in (page data from server)
const urlParams = new URLSearchParams(window.location.search);
const isBuilder = urlParams.get('nitrogen-builder');
// TODO: Add isPreview urlParams thing or something here to also get live updates when previewing.
if (!isBuilder) {
return;
}
function debouncedRequestPageUrl(timeout = 750){
let timer: NodeJS.Timeout;
let locationElement = document.querySelector('[data-nitrogen-location="' + nitrogenLocation + '"]') as HTMLDivElement;
let preOpacity = locationElement.style.opacity;
return (newData: {data:any}) => {
if(!locationElement) {
locationElement = document.querySelector('[data-nitrogen-location="' + nitrogenLocation + '"]') as HTMLDivElement;
}
if (locationElement) {
locationElement.style.opacity = '.5';
}
clearTimeout(timer);
timer = setTimeout(() => { requestPageUrl2(newData); if(locationElement) { if(preOpacity) locationElement.style.opacity = preOpacity; else locationElement.style.removeProperty('opacity'); } }, timeout);
};
}
const requestPageUrl = debouncedRequestPageUrl();
async function requestPageUrl2(newData: {data:any}) {
if(!window.nitrogenPHPClient?.pageRequestURL) {
throw new Error('No pageRequestURL found in window.nitrogenPHPClient');
}
if(!window.nitrogenPHPClient?.pageId) {
throw new Error('No pageId found in window.nitrogenPHPClient');
}
const locationElement = document.querySelector('[data-nitrogen-location="' + nitrogenLocation + '"]');
if (!locationElement) {
console.error('No location element found for nitrogenLocation', nitrogenLocation);
return;
}
const res = await fetch(window.nitrogenPHPClient.pageRequestURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
pageData: newData.data,
requestedData: {
...requestedData,
id: window.nitrogenPHPClient.pageId
}
}),
});
if (!res.ok) {
throw new Error('Failed to fetch page data');
}
const html = await res.text();
locationElement.innerHTML = html;
window.dispatchEvent(
new CustomEvent('nitrogen-page-data')
);
}
async function windowOnMessage(event: MessageEvent<any>) {
console.log('windowOnMessage', event);
if (!event.data) {
return;
}
let data;
try {
data = JSON.parse(event.data);
} catch (e) {
return;
}
if (data.channel !== 'nitrogen-builder') {
return;
}
if (data.type === 'corePageData') {
console.log('got corePageData from iframe', data.data);
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('nitrogen-page-data', {
detail: { data: data.data, requestedData },
})
);
}
// TODO: Reload page with new data.
try {
requestPageUrl(data);
} catch (e) {
console.error(e instanceof Error ? e.message : e);
}
} else if (data.type === 'patchPageData') {
console.log('got patchPageData from iframe', data.page);
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('nitrogen-page-data', {
detail: { data: data.data, requestedData },
})
);
}
// TODO: Reload page with new data.
try {
requestPageUrl(data);
} catch (e) {
console.error(e instanceof Error ? e.message : e);
}
} else if (data.type === 'patchDynamicData') {
const dynamicData = data.dynamicData;
// TODO: Reload page with new data.
const newData = {
...data,
dynamicData: {
...data.dynamicData,
...dynamicData.dynamicData,
}
}
try {
requestPageUrl(newData);
} catch(e) {
console.error(e instanceof Error ? e.message : e);
}
} else if (data.type === 'usersJoined') {
if (!window.nitrogen) return;
window.nitrogen.users = { ...window.nitrogen.users, ...data.users };
} else if (data.type === 'userLeft') {
if (!window.nitrogen) return;
const newUsers = { ...window.nitrogen.users };
delete newUsers[data.userSocketId];
window.nitrogen.users = newUsers;
} else if (data.type === 'startScreenUsage') {
if (!window.nitrogen) return;
const newScreenUsage = [
...window.nitrogen.screenUsage,
data.screenUsage,
];
window.nitrogen.screenUsage = newScreenUsage;
} else if (data.type === 'setScreenUsage') {
if (!window.nitrogen) return;
window.nitrogen.screenUsage = data.screenUsage;
} else if (data.type === 'stopScreenUsage') {
if (!window.nitrogen) return;
const newScreenUsage = window.nitrogen.screenUsage.filter((usage) => {
return !(
usage.screen === data.screenUsage.screen &&
usage.socketId === data.screenUsage.socketId
);
});
window.nitrogen.screenUsage = newScreenUsage;
}
}
function setup() {
if (!window.nitrogen) {
console.log('window.nitrogen is undefined');
setTimeout(setup, 100);
return;
}
console.log('connecting window to iFrame message listener');
window.addEventListener('message', windowOnMessage);
}
setup();
}
init({
type: nitrogenLocation
});