mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-09 17:33:55 +00:00
76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
|
|
const scriptTagId = 'ontime-override';
|
|
|
|
export const useRuntimeStylesheet = (pathToFile?: string): { shouldRender: boolean } => {
|
|
const [shouldRender, setShouldRender] = useState(false);
|
|
|
|
/**
|
|
* When a view mounts or the stylesheet path changes we need to handle potentially loading a new stylesheet
|
|
* - if no path is given, ensure there is no stylesheet loaded
|
|
* - if a path is given, fetch the stylesheet and inject it into the document head
|
|
* @returns { shouldRender: boolean } - after the stylesheet is handled and the clients are ready to render
|
|
*/
|
|
useEffect(() => {
|
|
if (!pathToFile) {
|
|
handleNoStylesheet();
|
|
return;
|
|
}
|
|
|
|
// there is already a stylesheet loaded, nothing further to do
|
|
if (document.getElementById(scriptTagId)) {
|
|
setShouldRender(true);
|
|
return;
|
|
}
|
|
|
|
setShouldRender(false);
|
|
|
|
fetchStylesheetData(pathToFile)
|
|
.then((data: string | undefined) => {
|
|
if (!data) {
|
|
console.error('Error loading stylesheet: no data');
|
|
return;
|
|
}
|
|
return injectStylesheet(data);
|
|
})
|
|
.catch((error: unknown) => {
|
|
console.error(`Error loading stylesheet: ${error}`);
|
|
})
|
|
.finally(() => {
|
|
// schedule render for next tick
|
|
setTimeout(() => setShouldRender(true), 0);
|
|
});
|
|
|
|
/**
|
|
* No stylesheet was provided, remove any existing stylesheet
|
|
*/
|
|
function handleNoStylesheet() {
|
|
document.getElementById(scriptTagId)?.remove();
|
|
setShouldRender(true);
|
|
}
|
|
|
|
/**
|
|
* Get data from backend
|
|
*/
|
|
async function fetchStylesheetData(path: string) {
|
|
const response = await fetch(path);
|
|
if (response.ok) {
|
|
return response.text();
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Add a stylesheet with given content to the document head
|
|
*/
|
|
async function injectStylesheet(styleContent: string) {
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.setAttribute('id', scriptTagId);
|
|
styleSheet.innerHTML = styleContent;
|
|
document.head.append(styleSheet);
|
|
}
|
|
}, [pathToFile]);
|
|
|
|
return { shouldRender };
|
|
};
|