feat: show network stats for collaboration
This commit is contained in:
parent
1e17c1967b
commit
8157c84d11
@ -73,6 +73,7 @@ export const getDefaultAppState = (): Omit<
|
|||||||
zenModeEnabled: false,
|
zenModeEnabled: false,
|
||||||
zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
|
zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
|
||||||
viewModeEnabled: false,
|
viewModeEnabled: false,
|
||||||
|
networkSpeed: "calculating...",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,6 +154,7 @@ const APP_STATE_STORAGE_CONF = (<
|
|||||||
zenModeEnabled: { browser: true, export: false },
|
zenModeEnabled: { browser: true, export: false },
|
||||||
zoom: { browser: true, export: false },
|
zoom: { browser: true, export: false },
|
||||||
viewModeEnabled: { browser: false, export: false },
|
viewModeEnabled: { browser: false, export: false },
|
||||||
|
networkSpeed: { browser: false, export: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
|
const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import { Point, simplify } from "points-on-curve";
|
import { Point, simplify } from "points-on-curve";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { RoughCanvas } from "roughjs/bin/canvas";
|
import { RoughCanvas } from "roughjs/bin/canvas";
|
||||||
@ -182,6 +183,7 @@ import LayerUI from "./LayerUI";
|
|||||||
import { Stats } from "./Stats";
|
import { Stats } from "./Stats";
|
||||||
import { Toast } from "./Toast";
|
import { Toast } from "./Toast";
|
||||||
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
|
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
|
||||||
|
import { getNetworkSpeed } from "../networkStats";
|
||||||
|
|
||||||
const { history } = createHistory();
|
const { history } = createHistory();
|
||||||
|
|
||||||
@ -461,6 +463,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
setAppState={this.setAppState}
|
setAppState={this.setAppState}
|
||||||
elements={this.scene.getElements()}
|
elements={this.scene.getElements()}
|
||||||
onClose={this.toggleStats}
|
onClose={this.toggleStats}
|
||||||
|
isCollaborating={this.props.isCollaborating}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{this.state.toastMessage !== null && (
|
{this.state.toastMessage !== null && (
|
||||||
@ -845,6 +848,21 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
this.addEventListeners();
|
this.addEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
prevState.showStats !== this.state.showStats ||
|
||||||
|
prevProps.isCollaborating !== this.props.isCollaborating
|
||||||
|
) {
|
||||||
|
if (this.state.showStats && this.props.isCollaborating) {
|
||||||
|
this.calculateNetStats();
|
||||||
|
navigator.connection.addEventListener("change", this.calculateNetStats);
|
||||||
|
} else {
|
||||||
|
navigator.connection.removeEventListener(
|
||||||
|
"change",
|
||||||
|
this.calculateNetStats,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
document
|
document
|
||||||
.querySelector(".excalidraw")
|
.querySelector(".excalidraw")
|
||||||
?.classList.toggle("Appearance_dark", this.state.appearance === "dark");
|
?.classList.toggle("Appearance_dark", this.state.appearance === "dark");
|
||||||
@ -970,6 +988,11 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private calculateNetStats = async () => {
|
||||||
|
const speed = await getNetworkSpeed();
|
||||||
|
const networkSpeed = speed === -1 ? "Error!" : speed;
|
||||||
|
this.setState({ networkSpeed });
|
||||||
|
};
|
||||||
// Copy/paste
|
// Copy/paste
|
||||||
|
|
||||||
private onCut = withBatchedUpdates((event: ClipboardEvent) => {
|
private onCut = withBatchedUpdates((event: ClipboardEvent) => {
|
||||||
|
@ -30,6 +30,7 @@ export const Stats = (props: {
|
|||||||
setAppState: React.Component<any, AppState>["setState"];
|
setAppState: React.Component<any, AppState>["setState"];
|
||||||
elements: readonly NonDeletedExcalidrawElement[];
|
elements: readonly NonDeletedExcalidrawElement[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
isCollaborating: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const [storageSizes, setStorageSizes] = useState<StorageSizes>({
|
const [storageSizes, setStorageSizes] = useState<StorageSizes>({
|
||||||
@ -192,6 +193,21 @@ export const Stats = (props: {
|
|||||||
{hash}
|
{hash}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{props.isCollaborating ? (
|
||||||
|
<>
|
||||||
|
<tr>
|
||||||
|
<th colSpan={2}>{t("stats.collaboration")}</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{t("stats.collaborators")}</td>
|
||||||
|
<td>{props.appState.collaborators.size}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{t("stats.networkSpeed")}</td>
|
||||||
|
<td>{props.appState.networkSpeed}</td>
|
||||||
|
</tr>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Island>
|
</Island>
|
||||||
|
@ -238,7 +238,10 @@
|
|||||||
"version": "Version",
|
"version": "Version",
|
||||||
"versionCopy": "Click to copy",
|
"versionCopy": "Click to copy",
|
||||||
"versionNotAvailable": "Version not available",
|
"versionNotAvailable": "Version not available",
|
||||||
"width": "Width"
|
"width": "Width",
|
||||||
|
"collaboration": "Collaboration",
|
||||||
|
"networkSpeed": "Network Speed",
|
||||||
|
"collaborators": "Collaborators"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"copyStyles": "Copied styles.",
|
"copyStyles": "Copied styles.",
|
||||||
|
37
src/networkStats.ts
Normal file
37
src/networkStats.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const IMAGE_URL =
|
||||||
|
"https://user-images.githubusercontent.com/11256141/107117897-76fa3880-68a3-11eb-9ec6-c214c7af373b.png";
|
||||||
|
const IMAGE_SIZE = 4525154; // in bytes
|
||||||
|
const calculateSpeed = (startTime: number, endTime: number) => {
|
||||||
|
const duration = (endTime - startTime) / 1000;
|
||||||
|
const imageSizeInBits = IMAGE_SIZE * 8;
|
||||||
|
let speed = imageSizeInBits / duration;
|
||||||
|
const suffix = ["bps", "kbps", "mbps", "gbps"];
|
||||||
|
let index = 0;
|
||||||
|
while (speed > 1024) {
|
||||||
|
index++;
|
||||||
|
speed = speed / 1024;
|
||||||
|
}
|
||||||
|
return `${speed.toFixed(2)} ${suffix[index]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const processImage = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const image = new Image();
|
||||||
|
let endTime: number;
|
||||||
|
image.onload = () => {
|
||||||
|
endTime = new Date().getTime();
|
||||||
|
const speed = calculateSpeed(startTime, endTime);
|
||||||
|
resolve(speed);
|
||||||
|
};
|
||||||
|
|
||||||
|
image.onerror = () => {
|
||||||
|
resolve(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const startTime = new Date().getTime();
|
||||||
|
image.src = `${IMAGE_URL}?t=${startTime}`; // start time acts as a cache buster so everytime new url is requested
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export const getNetworkSpeed = async () => {
|
||||||
|
return await processImage();
|
||||||
|
};
|
@ -88,6 +88,7 @@ export type AppState = {
|
|||||||
appearance: "light" | "dark";
|
appearance: "light" | "dark";
|
||||||
gridSize: number | null;
|
gridSize: number | null;
|
||||||
viewModeEnabled: boolean;
|
viewModeEnabled: boolean;
|
||||||
|
networkSpeed?: string;
|
||||||
|
|
||||||
/** top-most selected groups (i.e. does not include nested groups) */
|
/** top-most selected groups (i.e. does not include nested groups) */
|
||||||
selectedGroupIds: { [groupId: string]: boolean };
|
selectedGroupIds: { [groupId: string]: boolean };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user