Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for up to 1.5 seconds for external CSS to load #4335

Closed
wants to merge 2 commits into from
Closed
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ No changes to highlight.

## Bug Fixes:

No changes to highlight.
- Gradio will no longer hang forever when waiting for external CSS to load by [@akx](https://github.com/akx) in [PR 4335](https://github.com/gradio-app/gradio/pull/4335)


## Other Changes:

Expand Down
5 changes: 3 additions & 2 deletions js/app/src/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
style.innerHTML = css_string;
target.appendChild(style);
}
await mount_css(config.root + "/theme.css", document.head);
await mount_css(config.root + "/theme.css");
if (!config.stylesheets) return;

await Promise.all(
Expand All @@ -109,7 +109,8 @@
stylesheet.startsWith("http:") || stylesheet.startsWith("https:");
return mount_css(
absolute_link ? stylesheet : config.root + "/" + stylesheet,
document.head
// Wait up to 1.5 seconds for external stylesheets to load before continuing anyway.
absolute_link ? 1500 : undefined
);
})
);
Expand Down
30 changes: 22 additions & 8 deletions js/app/src/css.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
export function mount_css(url: string, target: HTMLElement): Promise<void> {
/**
* Loads a CSS file and appends it to the document head.
* The optional timeout parameter will resolve the promise without error
* if the CSS file has not loaded after the specified time.
*
* @param url URL to load.
* @param timeout Optional timeout, in milliseconds.
*/
export function mount_css(url: string, timeout?: number): Promise<unknown> {
const existing_link = document.querySelector(`link[href='${url}']`);

if (existing_link) return Promise.resolve();

const link = document.createElement("link");
link.rel = "stylesheet";
link.href = url;
// @ts-ignore
target.appendChild(link);
document.head.appendChild(link);

return new Promise((res, rej) => {
link.addEventListener("load", () => res());
link.addEventListener("error", () =>
rej(new Error(`Unable to preload CSS for ${url}`))
);
const loadPromise = new Promise((res, rej) => {
link.addEventListener("load", res);
link.addEventListener("error", (err) => {
console.error(`load_css: failed to load CSS`, url, err);
rej(err);
});
});

if (timeout) {
const timeoutPromise = new Promise((res) => setTimeout(res, timeout));
return Promise.race([loadPromise, timeoutPromise]);
}
return loadPromise;
}
4 changes: 2 additions & 2 deletions js/app/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ function create_custom_element() {

async connectedCallback() {
if (typeof FONTS !== "string") {
FONTS.forEach((f) => mount_css(f, document.head));
FONTS.forEach(mount_css);
}

await mount_css(ENTRY_CSS, document.head);
await mount_css(ENTRY_CSS);

const event = new CustomEvent("domchange", {
bubbles: true,
Expand Down