This commit is contained in:
LukeGus
2026-05-28 22:29:20 -05:00
parent 33dcde0827
commit 5777351145
238 changed files with 62303 additions and 98955 deletions
+55 -19
View File
@@ -65,6 +65,7 @@ export const GuacamoleDisplay = forwardRef<
typeof document === "undefined" ? true : document.hasFocus(),
);
const [isReady, setIsReady] = useState(false);
const [hasError, setHasError] = useState(false);
useImperativeHandle(ref, () => ({
disconnect: () => {
@@ -267,13 +268,20 @@ export const GuacamoleDisplay = forwardRef<
if (isConnectingRef.current) return;
isConnectingRef.current = true;
setIsReady(false);
setHasError(false);
let containerWidth = containerRef.current?.clientWidth || 0;
let containerHeight = containerRef.current?.clientHeight || 0;
// Wait two frames so the container is fully laid out before measuring.
await new Promise<void>((resolve) =>
requestAnimationFrame(() => requestAnimationFrame(() => resolve())),
);
const rect = containerRef.current?.getBoundingClientRect();
let containerWidth = rect?.width || 0;
let containerHeight = rect?.height || 0;
if (containerWidth < 100 || containerHeight < 100) {
containerWidth = 1280;
containerHeight = 720;
containerWidth = window.innerWidth || 1280;
containerHeight = window.innerHeight || 720;
}
const wsUrl = await getWebSocketUrl(containerWidth, containerHeight);
@@ -303,6 +311,11 @@ export const GuacamoleDisplay = forwardRef<
setIsReady(true);
};
const protocol = connectionConfig.protocol ?? connectionConfig.type;
if (protocol === "telnet") {
setIsReady(true);
}
const mouse = new Guacamole.Mouse(displayElement);
const sendMouseState = (state: Guacamole.Mouse.State) => {
displayElement.focus({ preventScroll: true });
@@ -351,8 +364,15 @@ export const GuacamoleDisplay = forwardRef<
case 2:
break;
case 3:
isConnectingRef.current = false;
setIsReady(true);
onConnect?.();
if (containerRef.current) {
const rect = containerRef.current.getBoundingClientRect();
const w = Math.round(rect.width);
const h = Math.round(rect.height);
if (w > 0 && h > 0) client.sendSize(w, h);
}
break;
case 4:
break;
@@ -366,8 +386,10 @@ export const GuacamoleDisplay = forwardRef<
};
client.onerror = (error: Guacamole.Status) => {
const errorMessage = error.message || "Connection error";
const errorMessage = error.message || t("guacamole.connectionError");
setIsReady(false);
setHasError(true);
isConnectingRef.current = false;
onError?.(errorMessage);
};
@@ -388,6 +410,24 @@ export const GuacamoleDisplay = forwardRef<
Guacamole.AudioPlayer.getInstance(stream, mimetype);
};
client.onfile = (
stream: Guacamole.InputStream,
mimetype: string,
filename: string,
) => {
const reader = new Guacamole.BlobReader(stream, mimetype);
reader.onend = () => {
const blob = reader.getBlob();
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
};
stream.sendAck("OK", Guacamole.Status.Code.SUCCESS);
};
client.connect();
}, [
getWebSocketUrl,
@@ -407,11 +447,7 @@ export const GuacamoleDisplay = forwardRef<
if (isVisible && !hasInitiatedRef.current) {
hasInitiatedRef.current = true;
requestAnimationFrame(() => {
if (isMountedRef.current) {
connect();
}
});
connect();
}
}, [isVisible, connect]);
@@ -475,26 +511,23 @@ export const GuacamoleDisplay = forwardRef<
if (!containerRef.current) return;
const resizeObserver = new ResizeObserver(() => {
rescaleDisplay(false);
if (resizeTimeoutRef.current) clearTimeout(resizeTimeoutRef.current);
resizeTimeoutRef.current = setTimeout(() => {
if (clientRef.current && containerRef.current) {
const w = containerRef.current.clientWidth;
const h = containerRef.current.clientHeight;
const rect = containerRef.current.getBoundingClientRect();
const w = Math.round(rect.width);
const h = Math.round(rect.height);
if (w > 0 && h > 0) clientRef.current.sendSize(w, h);
}
}, 200);
}, 150);
});
resizeObserver.observe(containerRef.current);
const initialTimeout = setTimeout(() => rescaleDisplay(true), 100);
return () => {
resizeObserver.disconnect();
clearTimeout(initialTimeout);
};
}, [rescaleDisplay]);
}, []);
const syncClipboard = useCallback(() => {
const client = clientRef.current;
@@ -553,7 +586,10 @@ export const GuacamoleDisplay = forwardRef<
}}
/>
<SimpleLoader visible={!isReady} message={connectingMessage} />
<SimpleLoader
visible={!isReady && !hasError}
message={connectingMessage}
/>
</div>
);
});