mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-10-30 18:34:22 +01:00 
			
		
		
		
	feat: support src collaborators (#5114)
* feat: support avatarURLfor collaborators * fix * better avatars :) * use position fixed for tooltips so it renders correctly when offsets updated * update docs * Update src/excalidraw-app/collab/CollabWrapper.tsx * rename avatarUrl to src
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| import { getClientColors, getClientInitials } from "../clients"; | ||||
| import { getClientColors } from "../clients"; | ||||
| import { Avatar } from "../components/Avatar"; | ||||
| import { centerScrollOn } from "../scene/scroll"; | ||||
| import { Collaborator } from "../types"; | ||||
| @@ -43,16 +43,15 @@ export const actionGoToCollaborator = register({ | ||||
|     } | ||||
|  | ||||
|     const { background, stroke } = getClientColors(clientId, appState); | ||||
|     const shortName = getClientInitials(collaborator.username); | ||||
|  | ||||
|     return ( | ||||
|       <Avatar | ||||
|         color={background} | ||||
|         border={stroke} | ||||
|         onClick={() => updateData(collaborator.pointer)} | ||||
|       > | ||||
|         {shortName} | ||||
|       </Avatar> | ||||
|         name={collaborator.username || ""} | ||||
|         src={collaborator.src} | ||||
|       /> | ||||
|     ); | ||||
|   }, | ||||
| }); | ||||
|   | ||||
| @@ -12,5 +12,11 @@ | ||||
|     cursor: pointer; | ||||
|     font-size: 0.8rem; | ||||
|     font-weight: 500; | ||||
|  | ||||
|     &-img { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       border-radius: 100%; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,20 +1,28 @@ | ||||
| import "./Avatar.scss"; | ||||
|  | ||||
| import React from "react"; | ||||
| import { getClientInitials } from "../clients"; | ||||
|  | ||||
| type AvatarProps = { | ||||
|   children: string; | ||||
|   onClick: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void; | ||||
|   color: string; | ||||
|   border: string; | ||||
|   name: string; | ||||
|   src?: string; | ||||
| }; | ||||
|  | ||||
| export const Avatar = ({ children, color, border, onClick }: AvatarProps) => ( | ||||
|   <div | ||||
|     className="Avatar" | ||||
|     style={{ background: color, border: `1px solid ${border}` }} | ||||
|     onClick={onClick} | ||||
|   > | ||||
|     {children} | ||||
| export const Avatar = ({ color, border, onClick, name, src }: AvatarProps) => { | ||||
|   const shortName = getClientInitials(name); | ||||
|   const style = src | ||||
|     ? undefined | ||||
|     : { background: color, border: `1px solid ${border}` }; | ||||
|   return ( | ||||
|     <div className="Avatar" style={style} onClick={onClick}> | ||||
|       {src ? ( | ||||
|         <img className="Avatar-img" src={src} alt={shortName} /> | ||||
|       ) : ( | ||||
|         shortName | ||||
|       )} | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| // container in body where the actual tooltip is appended to | ||||
| .excalidraw-tooltip { | ||||
|   position: absolute; | ||||
|   position: fixed; | ||||
|   z-index: 1000; | ||||
|  | ||||
|   padding: 8px; | ||||
|   | ||||
| @@ -17,6 +17,7 @@ Please add the latest change on the top under the correct section. | ||||
|  | ||||
| #### Features | ||||
|  | ||||
| - Support [`src`](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L50) for collaborators. Now onwards host can pass `src` to render the customized avatar for collaborators [#5114](https://github.com/excalidraw/excalidraw/pull/5114). | ||||
| - Support `libraryItems` argument in `initialData.libraryItems` and `updateScene({ libraryItems })` to be a Promise resolving to `LibraryItems`, and support functional update of `libraryItems` in [`updateScene({ libraryItems })`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#updateScene). [#5101](https://github.com/excalidraw/excalidraw/pull/5101). | ||||
| - Expose util [`mergeLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#mergeLibraryItems) [#5101](https://github.com/excalidraw/excalidraw/pull/5101). | ||||
| - Expose util [`exportToClipboard`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exportToClipboard) which allows to copy the scene contents to clipboard as `svg`, `png` or `json` [#5103](https://github.com/excalidraw/excalidraw/pull/5103). | ||||
|   | ||||
| @@ -512,7 +512,7 @@ You can use this function to update the scene with the sceneData. It accepts the | ||||
| | --- | --- | --- | | ||||
| | `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L17) | The `elements` to be updated in the scene | | ||||
| | `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L18) | The `appState` to be updated in the scene. | | ||||
| | `collaborators` | <pre>Map<string, <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L29">Collaborator></a></pre> | The list of collaborators to be updated in the scene. | | ||||
| | `collaborators` | <pre>Map<string, <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L35">Collaborator></a></pre> | The list of collaborators to be updated in the scene. | | ||||
| | `commitToHistory` | `boolean` | Implies if the `history (undo/redo)` should be recorded. Defaults to `false`. | | ||||
| | `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)> | ((currentItems: [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)>) => [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)>) | The `libraryItems` to be update in the scene. | | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,10 @@ const resolvablePromise = () => { | ||||
|  | ||||
| const renderTopRightUI = () => { | ||||
|   return ( | ||||
|     <button onClick={() => alert("This is dummy top right UI")}> | ||||
|     <button | ||||
|       onClick={() => alert("This is dummy top right UI")} | ||||
|       style={{ height: "2.5rem" }} | ||||
|     > | ||||
|       {" "} | ||||
|       Click me{" "} | ||||
|     </button> | ||||
| @@ -58,6 +61,7 @@ export default function App() { | ||||
|   const [exportWithDarkMode, setExportWithDarkMode] = useState(false); | ||||
|   const [exportEmbedScene, setExportEmbedScene] = useState(false); | ||||
|   const [theme, setTheme] = useState("light"); | ||||
|   const [isCollaborating, setIsCollaborating] = useState(false); | ||||
|  | ||||
|   const initialStatePromiseRef = useRef({ promise: null }); | ||||
|   if (!initialStatePromiseRef.current.promise) { | ||||
| @@ -228,6 +232,36 @@ export default function App() { | ||||
|             /> | ||||
|             Switch to Dark Theme | ||||
|           </label> | ||||
|           <label> | ||||
|             <input | ||||
|               type="checkbox" | ||||
|               checked={isCollaborating} | ||||
|               onChange={() => { | ||||
|                 if (!isCollaborating) { | ||||
|                   const collaborators = new Map(); | ||||
|                   collaborators.set("id1", { | ||||
|                     username: "Doremon", | ||||
|                     src: "doremon.png", | ||||
|                   }); | ||||
|                   collaborators.set("id2", { | ||||
|                     username: "Excalibot", | ||||
|                     src: "https://avatars.githubusercontent.com/excalibot", | ||||
|                   }); | ||||
|                   collaborators.set("id3", { | ||||
|                     username: "Pika", | ||||
|                     src: "pika.jpeg", | ||||
|                   }); | ||||
|                   excalidrawRef.current.updateScene({ collaborators }); | ||||
|                 } else { | ||||
|                   excalidrawRef.current.updateScene({ | ||||
|                     collaborators: new Map(), | ||||
|                   }); | ||||
|                 } | ||||
|                 setIsCollaborating(!isCollaborating); | ||||
|               }} | ||||
|             /> | ||||
|             Show collaborators | ||||
|           </label> | ||||
|           <div> | ||||
|             <button onClick={onCopy.bind(null, "png")}> | ||||
|               Copy to Clipboard as PNG | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								src/packages/excalidraw/example/public/doremon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/packages/excalidraw/example/public/doremon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 197 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/packages/excalidraw/example/public/pika.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/packages/excalidraw/example/public/pika.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 6.1 KiB | 
| @@ -45,6 +45,9 @@ export type Collaborator = { | ||||
|     background: string; | ||||
|     stroke: string; | ||||
|   }; | ||||
|   // The url of the collaborator's avatar, defaults to username intials | ||||
|   // if not present | ||||
|   src?: string; | ||||
| }; | ||||
|  | ||||
| export type DataURL = string & { _brand: "DataURL" }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Aakansha Doshi
					Aakansha Doshi