mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-11 07:58:11 -05:00
Compare commits
3 Commits
async-remo
...
autoreload
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab69d7292c | ||
|
|
36a99287d6 | ||
|
|
6560c59c8f |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -17894,7 +17894,8 @@
|
||||
}, _callee2);
|
||||
})));
|
||||
};
|
||||
socket.onclose = function() {
|
||||
socket.onclose = function(e) {
|
||||
var restarting = e.code === 1012;
|
||||
if (hasOpened) {
|
||||
(0, import_jquery38.default)(document).trigger({
|
||||
type: "shiny:disconnected",
|
||||
@@ -17902,7 +17903,7 @@
|
||||
});
|
||||
_this.$notifyDisconnected();
|
||||
}
|
||||
_this.onDisconnected();
|
||||
_this.onDisconnected(restarting);
|
||||
_this.$removeSocket();
|
||||
};
|
||||
return socket;
|
||||
@@ -17982,10 +17983,11 @@
|
||||
}, {
|
||||
key: "onDisconnected",
|
||||
value: function onDisconnected() {
|
||||
var $overlay = (0, import_jquery38.default)("#shiny-disconnected-overlay");
|
||||
if ($overlay.length === 0) {
|
||||
var reloading = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
|
||||
if ((0, import_jquery38.default)("#shiny-disconnected-overlay").length === 0) {
|
||||
(0, import_jquery38.default)(document.body).append('<div id="shiny-disconnected-overlay"></div>');
|
||||
}
|
||||
(0, import_jquery38.default)("#shiny-disconnected-overlay").toggleClass("reloading", reloading);
|
||||
if (this.$allowReconnect === true && this.$socket.allowReconnect === true || this.$allowReconnect === "force") {
|
||||
var delay = this.reconnectDelay.next();
|
||||
showReconnectDialog(delay);
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
inst/www/shared/shiny.min.css
vendored
2
inst/www/shared/shiny.min.css
vendored
File diff suppressed because one or more lines are too long
2
inst/www/shared/shiny.min.js
vendored
2
inst/www/shared/shiny.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -88,10 +88,7 @@ pre.shiny-text-output {
|
||||
|
||||
#shiny-disconnected-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
inset: 0;
|
||||
background-color: $shiny-disconnected-bg;
|
||||
opacity: 0.5;
|
||||
overflow: hidden;
|
||||
@@ -99,6 +96,17 @@ pre.shiny-text-output {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
html.autoreload-enabled #shiny-disconnected-overlay.reloading {
|
||||
opacity: 0;
|
||||
animation: fadeIn 250ms forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
to {
|
||||
opacity: 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
.table.shiny-table {
|
||||
@include table-padding($left: 12px, $right: 12px);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,86 @@
|
||||
/* eslint-disable unicorn/filename-case */
|
||||
const protocol = (window.location.protocol === "https:") ? "wss:" : "ws:";
|
||||
|
||||
document.documentElement.classList.add("autoreload-enabled");
|
||||
|
||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
// Add trailing slash to path, if necessary, before appending "autoreload"
|
||||
const defaultPath = window.location.pathname.replace(/\/?$/, "/") + "autoreload/";
|
||||
const defaultPath =
|
||||
window.location.pathname.replace(/\/?$/, "/") + "autoreload/";
|
||||
const defaultUrl = `${protocol}//${window.location.host}${defaultPath}`;
|
||||
|
||||
// By default, use the defaultUrl. But if there's a data-ws-url attribute on our
|
||||
// <script> tag, use that instead.
|
||||
const wsUrl = document.currentScript.dataset.wsUrl || defaultUrl;
|
||||
const ws = new WebSocket(wsUrl);
|
||||
const wsUrl = document.currentScript?.dataset?.wsUrl || defaultUrl;
|
||||
|
||||
ws.onmessage = function (event) {
|
||||
if (event.data === "autoreload") {
|
||||
window.location.reload();
|
||||
/**
|
||||
* Connects to an autoreload URL and waits for the server to tell us what to do.
|
||||
*
|
||||
* @param url The ws:// or wss:// URL to connect to.
|
||||
* @returns true if the server requests a reload, or false if the connection was
|
||||
* successfully established but then closed without the server requesting a
|
||||
* reload
|
||||
* @throws A nondescript error if the connection fails to be established.
|
||||
*/
|
||||
async function autoreload(url: string): Promise<boolean> {
|
||||
const ws = new WebSocket(url);
|
||||
|
||||
let success = false;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
ws.onopen = () => {
|
||||
success = true;
|
||||
};
|
||||
|
||||
ws.onerror = (err) => {
|
||||
reject(err);
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
if (!success) {
|
||||
reject(new Error("WebSocket connection failed"));
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onmessage = function (event) {
|
||||
if (event.data === "autoreload") {
|
||||
resolve(true);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
while (true) {
|
||||
try {
|
||||
if (await autoreload(wsUrl)) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
// It's possible for the autoreload() call to throw. If it does, that
|
||||
// means we tried but failed to connect to the autoreload socket. This
|
||||
// probably means that the entire `shiny run --reload` process was
|
||||
// restarted. As of today, the autoreload websocket port number is
|
||||
// randomly chosen for each `shiny run --reload` process, so it's
|
||||
// impossible for us to recover.
|
||||
console.debug("Giving up on autoreload");
|
||||
return;
|
||||
}
|
||||
// If we get here, the connection to the autoreload server was
|
||||
// successful but then got broken. Wait for a second, and then
|
||||
// try to re-establish the connection.
|
||||
await sleep(1000);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
initialize().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
export {};
|
||||
|
||||
@@ -244,7 +244,8 @@ class ShinyApp {
|
||||
};
|
||||
// Called when a successfully-opened websocket is closed, or when an
|
||||
// attempt to open a connection fails.
|
||||
socket.onclose = () => {
|
||||
socket.onclose = (e) => {
|
||||
const restarting = e.code === 1012; // Uvicorn sets this code when autoreloading
|
||||
// These things are needed only if we've successfully opened the
|
||||
// websocket.
|
||||
if (hasOpened) {
|
||||
@@ -257,7 +258,7 @@ class ShinyApp {
|
||||
this.$notifyDisconnected();
|
||||
}
|
||||
|
||||
this.onDisconnected(); // Must be run before this.$removeSocket()
|
||||
this.onDisconnected(restarting); // Must be run before this.$removeSocket()
|
||||
this.$removeSocket();
|
||||
};
|
||||
return socket;
|
||||
@@ -333,13 +334,12 @@ class ShinyApp {
|
||||
};
|
||||
})();
|
||||
|
||||
onDisconnected(): void {
|
||||
onDisconnected(reloading = false): void {
|
||||
// Add gray-out overlay, if not already present
|
||||
const $overlay = $("#shiny-disconnected-overlay");
|
||||
|
||||
if ($overlay.length === 0) {
|
||||
if ($("#shiny-disconnected-overlay").length === 0) {
|
||||
$(document.body).append('<div id="shiny-disconnected-overlay"></div>');
|
||||
}
|
||||
$("#shiny-disconnected-overlay").toggleClass("reloading", reloading);
|
||||
|
||||
// To try a reconnect, both the app (this.$allowReconnect) and the
|
||||
// server (this.$socket.allowReconnect) must allow reconnections, or
|
||||
|
||||
2
srcts/types/src/shiny/shinyapp.d.ts
vendored
2
srcts/types/src/shiny/shinyapp.d.ts
vendored
@@ -61,7 +61,7 @@ declare class ShinyApp {
|
||||
next: () => number;
|
||||
reset: () => void;
|
||||
};
|
||||
onDisconnected(): void;
|
||||
onDisconnected(reloading?: boolean): void;
|
||||
onConnected(): void;
|
||||
makeRequest(method: string, args: unknown[], onSuccess: OnSuccessRequest, onError: OnErrorRequest, blobs: Array<ArrayBuffer | Blob | string> | undefined): void;
|
||||
$sendMsg(msg: MessageValue): void;
|
||||
|
||||
Reference in New Issue
Block a user