Add user list component + snap to user functionality (#1749)

This commit is contained in:
Oliver Benns 2020-06-19 11:36:49 +01:00 committed by GitHub
parent 8f65e37dac
commit ca87ca6fe9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 333 additions and 32 deletions

View file

@ -0,0 +1,52 @@
import React from "react";
import { Avatar } from "../components/Avatar";
import { register } from "./register";
import { getClientColors, getClientInitials } from "../clients";
import { Collaborator } from "../types";
import { normalizeScroll } from "../scene";
export const actionGoToCollaborator = register({
name: "goToCollaborator",
perform: (_elements, appState, value) => {
const point = value as Collaborator["pointer"];
if (!point) {
return { appState, commitToHistory: false };
}
return {
appState: {
...appState,
scrollX: normalizeScroll(window.innerWidth / 2 - point.x),
scrollY: normalizeScroll(window.innerHeight / 2 - point.y),
// Close mobile menu
openMenu: appState.openMenu === "canvas" ? null : appState.openMenu,
},
commitToHistory: false,
};
},
PanelComponent: ({ appState, updateData, id }) => {
const clientId = id;
if (!clientId) {
return null;
}
const collaborator = appState.collaborators.get(clientId);
if (!collaborator) {
return null;
}
const { background } = getClientColors(clientId);
const shortName = getClientInitials(collaborator.username);
return (
<Avatar
color={background}
onClick={() => updateData(collaborator.pointer)}
>
{shortName}
</Avatar>
);
},
});

View file

@ -47,3 +47,5 @@ export {
} from "./actionMenu";
export { actionGroup, actionUngroup } from "./actionGroup";
export { actionGoToCollaborator } from "./actionNavigate";

View file

@ -101,7 +101,11 @@ export class ActionManager implements ActionsManagerInterface {
}));
}
renderAction = (name: ActionName) => {
// Id is an attribute that we can use to pass in data like keys.
// This is needed for dynamically generated action components
// like the user list. We can use this key to extract more
// data from app state. This is an alternative to generic prop hell!
renderAction = (name: ActionName, id?: string) => {
if (this.actions[name] && "PanelComponent" in this.actions[name]) {
const action = this.actions[name];
const PanelComponent = action.PanelComponent!;
@ -120,6 +124,7 @@ export class ActionManager implements ActionsManagerInterface {
elements={this.getElementsIncludingDeleted()}
appState={this.getAppState()}
updateData={updateData}
id={id}
/>
);
}

View file

@ -58,7 +58,8 @@ export type ActionName =
| "toggleFullScreen"
| "toggleShortcuts"
| "group"
| "ungroup";
| "ungroup"
| "goToCollaborator";
export interface Action {
name: ActionName;
@ -66,6 +67,7 @@ export interface Action {
elements: readonly ExcalidrawElement[];
appState: AppState;
updateData: (formData?: any) => void;
id?: string;
}>;
perform: ActionFn;
keyPriority?: number;