Add collaborators names (#1223)
* add random usernames * add username state * add username input * ability to set names * fix tests * set username oon mobile * remove auto generated names * remove commented code * always string * updaate snapshots * maintain username when clearing canvas * Update src/renderer/renderScene.ts Co-Authored-By: Lipis <lipiridis@gmail.com> * add border * fix styles Co-authored-by: Pete Hunt <petehunt@users.noreply.github.com> Co-authored-by: Faustino Kialungila <faustino.kialungila@gmail.com> Co-authored-by: Lipis <lipiridis@gmail.com>
This commit is contained in:
parent
0c3d34261e
commit
67805bc7a7
@ -10,6 +10,7 @@ import { getShortcutKey } from "../utils";
|
|||||||
import useIsMobile from "../is-mobile";
|
import useIsMobile from "../is-mobile";
|
||||||
import { register } from "./register";
|
import { register } from "./register";
|
||||||
import { newElementWith } from "../element/mutateElement";
|
import { newElementWith } from "../element/mutateElement";
|
||||||
|
import { AppState } from "../types";
|
||||||
|
|
||||||
export const actionChangeViewBackgroundColor = register({
|
export const actionChangeViewBackgroundColor = register({
|
||||||
name: "changeViewBackgroundColor",
|
name: "changeViewBackgroundColor",
|
||||||
@ -35,12 +36,15 @@ export const actionChangeViewBackgroundColor = register({
|
|||||||
|
|
||||||
export const actionClearCanvas = register({
|
export const actionClearCanvas = register({
|
||||||
name: "clearCanvas",
|
name: "clearCanvas",
|
||||||
perform: (elements) => {
|
perform: (elements, appState: AppState) => {
|
||||||
return {
|
return {
|
||||||
elements: elements.map((element) =>
|
elements: elements.map((element) =>
|
||||||
newElementWith(element, { isDeleted: true }),
|
newElementWith(element, { isDeleted: true }),
|
||||||
),
|
),
|
||||||
appState: getDefaultAppState(),
|
appState: {
|
||||||
|
...getDefaultAppState(),
|
||||||
|
username: appState.username,
|
||||||
|
},
|
||||||
commitToHistory: true,
|
commitToHistory: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -29,6 +29,7 @@ export function getDefaultAppState(): AppState {
|
|||||||
cursorButton: "up",
|
cursorButton: "up",
|
||||||
scrolledOutside: false,
|
scrolledOutside: false,
|
||||||
name: `excalidraw-${getDateTime()}`,
|
name: `excalidraw-${getDateTime()}`,
|
||||||
|
username: "",
|
||||||
isCollaborating: false,
|
isCollaborating: false,
|
||||||
isResizing: false,
|
isResizing: false,
|
||||||
isRotating: false,
|
isRotating: false,
|
||||||
|
@ -437,6 +437,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
} = {};
|
} = {};
|
||||||
const pointerViewportCoords: SceneState["remotePointerViewportCoords"] = {};
|
const pointerViewportCoords: SceneState["remotePointerViewportCoords"] = {};
|
||||||
const remoteSelectedElementIds: SceneState["remoteSelectedElementIds"] = {};
|
const remoteSelectedElementIds: SceneState["remoteSelectedElementIds"] = {};
|
||||||
|
const pointerUsernames: { [id: string]: string } = {};
|
||||||
this.state.collaborators.forEach((user, socketID) => {
|
this.state.collaborators.forEach((user, socketID) => {
|
||||||
if (user.selectedElementIds) {
|
if (user.selectedElementIds) {
|
||||||
for (const id of Object.keys(user.selectedElementIds)) {
|
for (const id of Object.keys(user.selectedElementIds)) {
|
||||||
@ -449,6 +450,9 @@ export class App extends React.Component<any, AppState> {
|
|||||||
if (!user.pointer) {
|
if (!user.pointer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (user.username) {
|
||||||
|
pointerUsernames[socketID] = user.username;
|
||||||
|
}
|
||||||
pointerViewportCoords[socketID] = sceneCoordsToViewportCoords(
|
pointerViewportCoords[socketID] = sceneCoordsToViewportCoords(
|
||||||
{
|
{
|
||||||
sceneX: user.pointer.x,
|
sceneX: user.pointer.x,
|
||||||
@ -483,6 +487,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
remotePointerViewportCoords: pointerViewportCoords,
|
remotePointerViewportCoords: pointerViewportCoords,
|
||||||
remotePointerButton: cursorButton,
|
remotePointerButton: cursorButton,
|
||||||
remoteSelectedElementIds: remoteSelectedElementIds,
|
remoteSelectedElementIds: remoteSelectedElementIds,
|
||||||
|
remotePointerUsernames: pointerUsernames,
|
||||||
shouldCacheIgnoreZoom: this.state.shouldCacheIgnoreZoom,
|
shouldCacheIgnoreZoom: this.state.shouldCacheIgnoreZoom,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -884,6 +889,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
socketID,
|
socketID,
|
||||||
pointerCoords,
|
pointerCoords,
|
||||||
button,
|
button,
|
||||||
|
username,
|
||||||
selectedElementIds,
|
selectedElementIds,
|
||||||
} = decryptedData.payload;
|
} = decryptedData.payload;
|
||||||
this.setState((state) => {
|
this.setState((state) => {
|
||||||
@ -894,6 +900,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
user.pointer = pointerCoords;
|
user.pointer = pointerCoords;
|
||||||
user.button = button;
|
user.button = button;
|
||||||
user.selectedElementIds = selectedElementIds;
|
user.selectedElementIds = selectedElementIds;
|
||||||
|
user.username = username;
|
||||||
state.collaborators.set(socketID, user);
|
state.collaborators.set(socketID, user);
|
||||||
return state;
|
return state;
|
||||||
});
|
});
|
||||||
@ -947,6 +954,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
pointerCoords: payload.pointerCoords,
|
pointerCoords: payload.pointerCoords,
|
||||||
button: payload.button || "up",
|
button: payload.button || "up",
|
||||||
selectedElementIds: this.state.selectedElementIds,
|
selectedElementIds: this.state.selectedElementIds,
|
||||||
|
username: this.state.username,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return this._broadcastSocketData(
|
return this._broadcastSocketData(
|
||||||
|
@ -133,6 +133,12 @@ export const LayerUI = React.memo(
|
|||||||
<RoomDialog
|
<RoomDialog
|
||||||
isCollaborating={appState.isCollaborating}
|
isCollaborating={appState.isCollaborating}
|
||||||
collaboratorCount={appState.collaborators.size}
|
collaboratorCount={appState.collaborators.size}
|
||||||
|
username={appState.username}
|
||||||
|
onUsernameChange={(username) => {
|
||||||
|
setAppState({
|
||||||
|
username,
|
||||||
|
});
|
||||||
|
}}
|
||||||
onRoomCreate={onRoomCreate}
|
onRoomCreate={onRoomCreate}
|
||||||
onRoomDestroy={onRoomDestroy}
|
onRoomDestroy={onRoomDestroy}
|
||||||
/>
|
/>
|
||||||
|
@ -90,6 +90,8 @@ export function MobileMenu({
|
|||||||
<RoomDialog
|
<RoomDialog
|
||||||
isCollaborating={appState.isCollaborating}
|
isCollaborating={appState.isCollaborating}
|
||||||
collaboratorCount={appState.collaborators.size}
|
collaboratorCount={appState.collaborators.size}
|
||||||
|
username={appState.username}
|
||||||
|
onUsernameChange={(username) => setAppState({ username })}
|
||||||
onRoomCreate={onRoomCreate}
|
onRoomCreate={onRoomCreate}
|
||||||
onRoomDestroy={onRoomDestroy}
|
onRoomDestroy={onRoomDestroy}
|
||||||
/>
|
/>
|
||||||
|
@ -36,6 +36,33 @@
|
|||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.RoomDialog-usernameContainer {
|
||||||
|
display: flex;
|
||||||
|
margin: 1.5em 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomDialog-usernameLabel {
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomDialog-username {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
margin-left: 1em;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
height: 2.5rem;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
border-radius: var(--space-factor);
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
.RoomDialog-link:hover {
|
.RoomDialog-link:hover {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,19 @@ import { AppState } from "../types";
|
|||||||
|
|
||||||
function RoomModal({
|
function RoomModal({
|
||||||
activeRoomLink,
|
activeRoomLink,
|
||||||
|
username,
|
||||||
|
onUsernameChange,
|
||||||
onRoomCreate,
|
onRoomCreate,
|
||||||
onRoomDestroy,
|
onRoomDestroy,
|
||||||
}: {
|
}: {
|
||||||
activeRoomLink: string;
|
activeRoomLink: string;
|
||||||
|
username: string;
|
||||||
|
onUsernameChange: (username: string) => void;
|
||||||
onRoomCreate: () => void;
|
onRoomCreate: () => void;
|
||||||
onRoomDestroy: () => void;
|
onRoomDestroy: () => void;
|
||||||
}) {
|
}) {
|
||||||
const roomLinkInput = useRef<HTMLInputElement>(null);
|
const roomLinkInput = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
function copyRoomLink() {
|
function copyRoomLink() {
|
||||||
copyTextToSystemClipboard(activeRoomLink);
|
copyTextToSystemClipboard(activeRoomLink);
|
||||||
if (roomLinkInput.current) {
|
if (roomLinkInput.current) {
|
||||||
@ -71,6 +76,17 @@ function RoomModal({
|
|||||||
onPointerDown={selectInput}
|
onPointerDown={selectInput}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="RoomDialog-usernameContainer">
|
||||||
|
<label className="RoomDialog-usernameLabel" htmlFor="username">
|
||||||
|
Username:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="username"
|
||||||
|
value={username || ""}
|
||||||
|
className="RoomDialog-username"
|
||||||
|
onChange={(event) => onUsernameChange(event.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
|
<p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
|
||||||
<p>
|
<p>
|
||||||
<span role="img" aria-hidden="true">
|
<span role="img" aria-hidden="true">
|
||||||
@ -99,11 +115,15 @@ function RoomModal({
|
|||||||
export function RoomDialog({
|
export function RoomDialog({
|
||||||
isCollaborating,
|
isCollaborating,
|
||||||
collaboratorCount,
|
collaboratorCount,
|
||||||
|
username,
|
||||||
|
onUsernameChange,
|
||||||
onRoomCreate,
|
onRoomCreate,
|
||||||
onRoomDestroy,
|
onRoomDestroy,
|
||||||
}: {
|
}: {
|
||||||
isCollaborating: AppState["isCollaborating"];
|
isCollaborating: AppState["isCollaborating"];
|
||||||
collaboratorCount: number;
|
collaboratorCount: number;
|
||||||
|
username: string;
|
||||||
|
onUsernameChange: (username: string) => void;
|
||||||
onRoomCreate: () => void;
|
onRoomCreate: () => void;
|
||||||
onRoomDestroy: () => void;
|
onRoomDestroy: () => void;
|
||||||
}) {
|
}) {
|
||||||
@ -149,6 +169,8 @@ export function RoomDialog({
|
|||||||
>
|
>
|
||||||
<RoomModal
|
<RoomModal
|
||||||
activeRoomLink={activeRoomLink}
|
activeRoomLink={activeRoomLink}
|
||||||
|
username={username}
|
||||||
|
onUsernameChange={onUsernameChange}
|
||||||
onRoomCreate={onRoomCreate}
|
onRoomCreate={onRoomCreate}
|
||||||
onRoomDestroy={onRoomDestroy}
|
onRoomDestroy={onRoomDestroy}
|
||||||
/>
|
/>
|
||||||
|
@ -54,6 +54,7 @@ export type SocketUpdateDataSource = {
|
|||||||
pointerCoords: { x: number; y: number };
|
pointerCoords: { x: number; y: number };
|
||||||
button: "down" | "up";
|
button: "down" | "up";
|
||||||
selectedElementIds: AppState["selectedElementIds"];
|
selectedElementIds: AppState["selectedElementIds"];
|
||||||
|
username: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -330,6 +330,7 @@ export function renderScene(
|
|||||||
// Paint remote pointers
|
// Paint remote pointers
|
||||||
for (const clientId in sceneState.remotePointerViewportCoords) {
|
for (const clientId in sceneState.remotePointerViewportCoords) {
|
||||||
let { x, y } = sceneState.remotePointerViewportCoords[clientId];
|
let { x, y } = sceneState.remotePointerViewportCoords[clientId];
|
||||||
|
const username = sceneState.remotePointerUsernames[clientId];
|
||||||
|
|
||||||
const width = 9;
|
const width = 9;
|
||||||
const height = 14;
|
const height = 14;
|
||||||
@ -383,6 +384,41 @@ export function renderScene(
|
|||||||
context.lineTo(x, y);
|
context.lineTo(x, y);
|
||||||
context.fill();
|
context.fill();
|
||||||
context.stroke();
|
context.stroke();
|
||||||
|
|
||||||
|
if (!isOutOfBounds && username) {
|
||||||
|
const offsetX = x + width;
|
||||||
|
const offsetY = y + height;
|
||||||
|
const paddingHorizontal = 4;
|
||||||
|
const paddingVertical = 4;
|
||||||
|
const measure = context.measureText(username);
|
||||||
|
const measureHeight =
|
||||||
|
measure.actualBoundingBoxDescent + measure.actualBoundingBoxAscent;
|
||||||
|
|
||||||
|
// Border
|
||||||
|
context.fillStyle = stroke;
|
||||||
|
context.globalAlpha = globalAlpha;
|
||||||
|
context.fillRect(
|
||||||
|
offsetX - 1,
|
||||||
|
offsetY - 1,
|
||||||
|
measure.width + 2 * paddingHorizontal + 2,
|
||||||
|
measureHeight + 2 * paddingVertical + 2,
|
||||||
|
);
|
||||||
|
// Background
|
||||||
|
context.fillStyle = background;
|
||||||
|
context.fillRect(
|
||||||
|
offsetX,
|
||||||
|
offsetY,
|
||||||
|
measure.width + 2 * paddingHorizontal,
|
||||||
|
measureHeight + 2 * paddingVertical,
|
||||||
|
);
|
||||||
|
context.fillStyle = "#ffffff";
|
||||||
|
context.fillText(
|
||||||
|
username,
|
||||||
|
offsetX + paddingHorizontal,
|
||||||
|
offsetY + paddingVertical + measure.actualBoundingBoxAscent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
context.strokeStyle = strokeStyle;
|
context.strokeStyle = strokeStyle;
|
||||||
context.fillStyle = fillStyle;
|
context.fillStyle = fillStyle;
|
||||||
context.globalAlpha = globalAlpha;
|
context.globalAlpha = globalAlpha;
|
||||||
|
@ -54,6 +54,7 @@ export function exportToCanvas(
|
|||||||
remotePointerViewportCoords: {},
|
remotePointerViewportCoords: {},
|
||||||
remoteSelectedElementIds: {},
|
remoteSelectedElementIds: {},
|
||||||
shouldCacheIgnoreZoom: false,
|
shouldCacheIgnoreZoom: false,
|
||||||
|
remotePointerUsernames: {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
renderScrollbars: false,
|
renderScrollbars: false,
|
||||||
|
@ -11,6 +11,7 @@ export type SceneState = {
|
|||||||
remotePointerViewportCoords: { [id: string]: { x: number; y: number } };
|
remotePointerViewportCoords: { [id: string]: { x: number; y: number } };
|
||||||
remotePointerButton?: { [id: string]: string | undefined };
|
remotePointerButton?: { [id: string]: string | undefined };
|
||||||
remoteSelectedElementIds: { [elementId: string]: string[] };
|
remoteSelectedElementIds: { [elementId: string]: string[] };
|
||||||
|
remotePointerUsernames: { [id: string]: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SceneScroll = {
|
export type SceneScroll = {
|
||||||
|
@ -38,6 +38,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -233,6 +234,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -348,6 +350,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -616,6 +619,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -772,6 +776,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -967,6 +972,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -1221,6 +1227,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -1589,6 +1596,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2205,6 +2213,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2320,6 +2329,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2435,6 +2445,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2550,6 +2561,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2687,6 +2699,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2824,6 +2837,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -2961,6 +2975,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -3076,6 +3091,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -3191,6 +3207,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -3328,6 +3345,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -3443,6 +3461,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": true,
|
"shouldCacheIgnoreZoom": true,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -3513,6 +3532,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -4379,6 +4399,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -4793,6 +4814,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -5116,6 +5138,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -5352,6 +5375,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -5521,6 +5545,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -6339,6 +6364,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -7050,6 +7076,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -7658,6 +7685,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -8168,6 +8196,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -8629,6 +8658,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -8997,6 +9027,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -9276,6 +9307,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -9486,6 +9518,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -10359,6 +10392,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -11123,6 +11157,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -11782,6 +11817,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -12336,6 +12372,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -12707,6 +12744,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -12761,6 +12799,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": true,
|
"shouldCacheIgnoreZoom": true,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -12815,6 +12854,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
@ -13106,6 +13146,7 @@ Object {
|
|||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ export type AppState = {
|
|||||||
cursorButton: "up" | "down";
|
cursorButton: "up" | "down";
|
||||||
scrolledOutside: boolean;
|
scrolledOutside: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
|
username: string;
|
||||||
isCollaborating: boolean;
|
isCollaborating: boolean;
|
||||||
isResizing: boolean;
|
isResizing: boolean;
|
||||||
isRotating: boolean;
|
isRotating: boolean;
|
||||||
@ -53,6 +54,7 @@ export type AppState = {
|
|||||||
};
|
};
|
||||||
button?: "up" | "down";
|
button?: "up" | "down";
|
||||||
selectedElementIds?: AppState["selectedElementIds"];
|
selectedElementIds?: AppState["selectedElementIds"];
|
||||||
|
username?: string | null;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
shouldCacheIgnoreZoom: boolean;
|
shouldCacheIgnoreZoom: boolean;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user