Offline troubleshoot when server disconnects

Summary:
If there server disconnects, we used to show a red box message on the lower left section of the screen. It didn't say much other than the server had disconnected.
If you are aware of what the server is, then you may try to manually restart it.

Instead of doing that, a much better experience is to show the no connection troubleshoot with the button to start the server or with instructions on how to achieve this.

Reviewed By: antonk52

Differential Revision: D48467308

fbshipit-source-id: 0ffded95789c7548d9f1e1a9127409e02e72ab8c
This commit is contained in:
Lorenzo Blasa
2023-08-18 07:59:51 -07:00
committed by Facebook GitHub Bot
parent c1c586d2c7
commit 4ff9279a0b
7 changed files with 275 additions and 28 deletions

View File

@@ -270,7 +270,7 @@ function showCompileError() {
// Symbolicating compile errors is wasted effort // Symbolicating compile errors is wasted effort
// because the stack trace is meaningless: // because the stack trace is meaningless:
(error as any).preventSymbolication = true; (error as any).preventSymbolication = true;
window.flipperShowError?.(message); window.flipperShowMessage?.(message);
throw error; throw error;
} }

View File

@@ -17,7 +17,8 @@ declare global {
debug: boolean; debug: boolean;
}; };
flipperShowError?(error: string): void; flipperShowMessage?(message: string): void;
flipperHideError?(): void; flipperHideMessage?(): void;
flipperShowNoConnection?(): void;
} }
} }

View File

@@ -47,13 +47,13 @@ async function start() {
(state: FlipperServerState) => { (state: FlipperServerState) => {
switch (state) { switch (state) {
case FlipperServerState.CONNECTING: case FlipperServerState.CONNECTING:
window.flipperShowError?.('Connecting to server...'); window.flipperShowMessage?.('Connecting to server...');
break; break;
case FlipperServerState.CONNECTED: case FlipperServerState.CONNECTED:
window?.flipperHideError?.(); window?.flipperHideMessage?.();
break; break;
case FlipperServerState.DISCONNECTED: case FlipperServerState.DISCONNECTED:
window?.flipperShowError?.('Lost connection to server'); window?.flipperShowNoConnection?.();
break; break;
} }
}, },
@@ -78,17 +78,17 @@ async function start() {
// This prevent issues where the render host is referred at module initialisation level, // This prevent issues where the render host is referred at module initialisation level,
// but not set yet, which might happen when using normal imports. // but not set yet, which might happen when using normal imports.
// TODO: remove // TODO: remove
window.flipperShowError?.('Connected to Flipper Server successfully'); window.flipperShowMessage?.('Connected to Flipper Server successfully');
// @ts-ignore // @ts-ignore
// eslint-disable-next-line import/no-commonjs // eslint-disable-next-line import/no-commonjs
require('flipper-ui-core').startFlipperDesktop(flipperServer); require('flipper-ui-core').startFlipperDesktop(flipperServer);
window.flipperHideError?.(); window.flipperHideMessage?.();
} }
start().catch((e) => { start().catch((e) => {
console.error('Failed to start flipper-ui-browser', e); console.error('Failed to start flipper-ui-browser', e);
window.flipperShowError?.('Failed to start flipper-ui-browser: ' + e); window.flipperShowMessage?.('Failed to start flipper-ui-browser: ' + e);
}); });
async function initializePWA() { async function initializePWA() {

View File

@@ -169,7 +169,7 @@ export function initializeRenderHost(
); );
}, },
restartFlipper() { restartFlipper() {
window.flipperShowError?.( window.flipperShowMessage?.(
'Flipper settings have changed, please restart flipper server for the changes to take effect', 'Flipper settings have changed, please restart flipper server for the changes to take effect',
); );
}, },

View File

@@ -21,7 +21,7 @@
} }
</script> </script>
<style> <style>
#loading { .message {
-webkit-app-region: drag; -webkit-app-region: drag;
z-index: 999999; z-index: 999999;
position: absolute; position: absolute;
@@ -39,12 +39,92 @@
text-align: center; text-align: center;
} }
.console {
font-family: 'Fira Mono';
width: 600px;
height: 250px;
box-sizing: border-box;
margin: auto;
}
.console header {
border-top-left-radius: 15px;
border-top-right-radius: 15px;
background-color: #9254de;
height: 45px;
line-height: 45px;
text-align: center;
color: white;
}
.console .consolebody {
border-bottom-left-radius: 15px;
border-bottom-right-radius: 15px;
box-sizing: border-box;
padding: 0px 10px;
height: calc(100% - 40px);
overflow: scroll;
background-color: #000;
color: white;
text-align: left;
}
input[type="submit"] {
background-color: #9254de;
color: white;
font-family: system-ui;
font-size: 15px;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #722ed1;
}
input[type="submit"]:active {
background-color: #722ed1;
}
#troubleshoot {
display: none;
background-color: white;
}
</style> </style>
</head> </head>
<body> <body>
<div id="troubleshoot" class="message">
<div>
<b>Flipper is not running in the background</b>
<p>It can be started by clicking the button below.</p>
<form action="flipper-launcher://start-server">
<input type="submit" value="Start" />
</form>
<br />
<p>
Flipper will automatically reload once the connection is re-established.
</p>
<p>If is taking a bit longer than it should, you can manually start Flipper.</p>
<p>From the terminal, please run:</p>
<div class="console">
<header>
<p>shell</p>
</header>
<div class="consolebody">
<p>> open -a 'Flipper' --args '--server'</p>
</div>
</div>
</div>
</div>
<div id="root"> <div id="root">
<div id="loading"> <div id="loading" class="message">
Connecting... Connecting...
</div> </div>
</div> </div>
@@ -56,6 +136,39 @@
let suppressErrors = false; let suppressErrors = false;
let connected = false; let connected = false;
// Listen to changes in the network state, reload when online.
// This handles the case when the device is completely offline
// i.e. no network connection.
window.addEventListener('online', () => {
window.location.reload();
});
// Check if the server is responding & reload the page if it is.
// This handles the case when the device is online, but the server
// is offline or misbehaving.
async function checkNetworkAndReload() {
try {
const response = await fetch('.');
if (response.status >= 200 && response.status < 500) {
window.location.reload();
return;
}
} catch {
// Unable to connect to the server, ignore.
}
window.setTimeout(checkNetworkAndReload, 2500);
}
function showNoConnection() {
const root = document.getElementById('root');
root.remove();
const troubleshoot = document.getElementById('troubleshoot');
troubleshoot.style.display = 'flex';
checkNetworkAndReload();
}
const params = new URL(location.href).searchParams; const params = new URL(location.href).searchParams;
let token = params.get('token'); let token = params.get('token');
if (!token) { if (!token) {
@@ -73,7 +186,7 @@
if (typeof message.event === 'string') { if (typeof message.event === 'string') {
switch (message.event) { switch (message.event) {
case 'hasErrors': { case 'hasErrors': {
openError(message.payload); showMessage(message.payload);
suppressErrors = true; suppressErrors = true;
break; break;
} }
@@ -90,10 +203,10 @@
socket.addEventListener('error', (e) => { socket.addEventListener('error', (e) => {
if (!connected) { if (!connected) {
openError('Socket failed to connect. Is the server running? Have you provided a valid authentication token?'); showMessage('Socket failed to connect. Is the server running? Have you provided a valid authentication token?');
} }
else { else {
openError('Socket failed with error.'); showMessage('Socket failed with error.');
} }
suppressErrors = true; suppressErrors = true;
@@ -103,7 +216,7 @@
connected = true; connected = true;
}) })
function openError(text) { function showMessage(text) {
if (suppressErrors) { if (suppressErrors) {
return; return;
} }
@@ -113,7 +226,8 @@
box.textContent = text; box.textContent = text;
} }
} }
window.flipperShowError = openError; window.flipperShowMessage = showMessage;
window.flipperShowNoConnection = showNoConnection;
// load correct theme (n.b. this doesn't handle system value specifically, will assume light in such cases) // load correct theme (n.b. this doesn't handle system value specifically, will assume light in such cases)
try { try {
@@ -132,7 +246,7 @@
script.src = window.flipperConfig.entryPoint; script.src = window.flipperConfig.entryPoint;
script.onerror = (e) => { script.onerror = (e) => {
openError('Failed to load entry point. Check Chrome console for more info.'); showMessage('Failed to load entry point. Check Chrome console for more info.');
}; };
document.body.appendChild(script); document.body.appendChild(script);

View File

@@ -21,7 +21,7 @@
} }
</script> </script>
<style> <style>
#loading { .message {
-webkit-app-region: drag; -webkit-app-region: drag;
z-index: 999999; z-index: 999999;
position: absolute; position: absolute;
@@ -39,6 +39,60 @@
text-align: center; text-align: center;
} }
.console {
font-family: 'Fira Mono';
width: 600px;
height: 250px;
box-sizing: border-box;
margin: auto;
}
.console header {
border-top-left-radius: 15px;
border-top-right-radius: 15px;
background-color: #9254de;
height: 45px;
line-height: 45px;
text-align: center;
color: white;
}
.console .consolebody {
border-bottom-left-radius: 15px;
border-bottom-right-radius: 15px;
box-sizing: border-box;
padding: 0px 10px;
height: calc(100% - 40px);
overflow: scroll;
background-color: #000;
color: white;
text-align: left;
}
input[type="submit"] {
background-color: #9254de;
color: white;
font-family: system-ui;
font-size: 15px;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #722ed1;
}
input[type="submit"]:active {
background-color: #722ed1;
}
#troubleshoot {
display: none;
background-color: white;
}
.__infinity-dev-box-error { .__infinity-dev-box-error {
background-color: red; background-color: red;
font-family: monospace; font-family: monospace;
@@ -53,8 +107,34 @@
</head> </head>
<body> <body>
<div id="troubleshoot" class="message">
<div>
<b>Flipper is not running in the background</b>
<p>It can be started by clicking the button below.</p>
<form action="flipper-launcher://start-server">
<input type="submit" value="Start" />
</form>
<br />
<p>
Flipper will automatically reload once the connection is re-established.
</p>
<p>If is taking a bit longer than it should, you can manually start Flipper.</p>
<p>From the terminal, please run:</p>
<div class="console">
<header>
<p>shell</p>
</header>
<div class="consolebody">
<p>> open -a 'Flipper' --args '--server'</p>
</div>
</div>
</div>
</div>
<div id="root"> <div id="root">
<div id="loading"> <div id="loading" class="message">
Loading... Loading...
</div> </div>
</div> </div>
@@ -66,7 +146,40 @@
window.global = window; window.global = window;
let suppressErrors = false; let suppressErrors = false;
function openError(text) { // Listen to changes in the network state, reload when online.
// This handles the case when the device is completely offline
// i.e. no network connection.
window.addEventListener('online', () => {
window.location.reload();
});
// Check if the server is responding & reload the page if it is.
// This handles the case when the device is online, but the server
// is offline or misbehaving.
async function checkNetworkAndReload() {
try {
const response = await fetch('.');
if (response.status >= 200 && response.status < 500) {
window.location.reload();
return;
}
} catch {
// Unable to connect to the server, ignore.
}
window.setTimeout(checkNetworkAndReload, 2500);
}
function showNoConnection() {
const root = document.getElementById('root');
root.remove();
const troubleshoot = document.getElementById('troubleshoot');
troubleshoot.style.display = 'flex';
checkNetworkAndReload();
}
function showMessage(text) {
if (suppressErrors) { if (suppressErrors) {
return; return;
} }
@@ -82,14 +195,15 @@
box.appendChild(closeButton); box.appendChild(closeButton);
} }
} }
window.flipperShowError = openError; window.flipperShowMessage = showMessage;
window.flipperHideError = () => { window.flipperShowNoConnection = showNoConnection;
window.flipperHideMessage = () => {
const box = document.querySelector('.__infinity-dev-box-error'); const box = document.querySelector('.__infinity-dev-box-error');
box.setAttribute('hidden', true); box.setAttribute('hidden', true);
} }
const closeButton = document.createElement('button'); const closeButton = document.createElement('button');
closeButton.addEventListener('click', window.flipperHideError); closeButton.addEventListener('click', window.flipperHideMessage);
closeButton.textContent = 'X'; closeButton.textContent = 'X';
// load correct theme (n.b. this doesn't handle system value specifically, will assume light in such cases) // load correct theme (n.b. this doesn't handle system value specifically, will assume light in such cases)
@@ -109,7 +223,7 @@
script.src = window.flipperConfig.entryPoint; script.src = window.flipperConfig.entryPoint;
script.onerror = (e) => { script.onerror = (e) => {
openError('Script failure. Check Chrome console for more info.'); showMessage('Script failure. Check Chrome console for more info.');
}; };
document.body.appendChild(script); document.body.appendChild(script);

View File

@@ -42,17 +42,16 @@
height: 250px; height: 250px;
box-sizing: border-box; box-sizing: border-box;
margin: auto; margin: auto;
} }
.console header { .console header {
border-top-left-radius: 15px; border-top-left-radius: 15px;
border-top-right-radius: 15px; border-top-right-radius: 15px;
background-color: #4267B2; background-color: #9254de;
height: 45px; height: 45px;
line-height: 45px; line-height: 45px;
text-align: center; text-align: center;
color: #DDD; color: white;
} }
.console .consolebody { .console .consolebody {
@@ -67,6 +66,25 @@
text-align: left; text-align: left;
} }
input[type="submit"] {
background-color: #9254de;
color: white;
font-family: system-ui;
font-size: 15px;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #722ed1;
}
input[type="submit"]:active {
background-color: #722ed1;
}
</style> </style>
</head> </head>