@@ -4,12 +4,9 @@ import { ColorPicker } from "./ColorPicker";
44import { StrokeControl } from "./StrokeControl" ;
55import { toast } from "sonner" ;
66import { io } from "socket.io-client" ;
7- < << << << Updated upstream
8- = = === ==
97import tinycolor from "tinycolor2" ;
108import { jsPDF } from "jspdf" ;
119import C2S from "canvas2svg" ;
12- >>> >>> > Stashed changes
1310
1411export const Canvas = ( ) => {
1512 const canvasRef = useRef ( null ) ;
@@ -37,9 +34,7 @@ export const Canvas = () => {
3734 const [ socket , setSocket ] = useState ( null ) ;
3835 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
3936
40- const [ isLoggedIn , setIsLoggedIn ] = useState (
41- ! ! localStorage . getItem ( "token" )
42- ) ;
37+ const [ isLoggedIn , setIsLoggedIn ] = useState ( ! ! localStorage . getItem ( "token" ) ) ;
4338
4439 const handleLogout = async ( ) => {
4540 // ... (existing logout logic - unchanged)
@@ -263,9 +258,15 @@ export const Canvas = () => {
263258 startPoint . current = { x, y } ;
264259 setIsDrawing ( true ) ;
265260
266- if ( activeTool === "pen" || activeTool === "eraser" ) {
261+ // Begin drawing for pen, eraser, or brush tools
262+ if (
263+ activeTool === "pen" ||
264+ activeTool === "eraser" ||
265+ activeTool . startsWith ( "brush-" )
266+ ) {
267267 ctx . beginPath ( ) ;
268268 ctx . moveTo ( x , y ) ;
269+
269270 if ( joined && socket )
270271 socket . emit ( "draw" , {
271272 roomId,
@@ -278,28 +279,28 @@ export const Canvas = () => {
278279 } ) ;
279280 }
280281
281- // Save snapshot for preview tools
282+ // Snapshot for line/rectangle previews
282283 if ( activeTool === "line" || activeTool === "rectangle" ) {
283- // Snapshot must be taken from the *un-transformed* context
284- ctx . restore ( ) ; // Restore *before* getImageData
284+ ctx . restore ( ) ; // restore before snapshot
285285 snapshot . current = ctx . getImageData ( 0 , 0 , canvas . width , canvas . height ) ;
286- // Re-save to apply transform again for next draw
287286 ctx . save ( ) ;
288287 ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
289288 ctx . translate ( offset . x , offset . y ) ;
290289 ctx . scale ( scale , scale ) ;
291290 }
291+
292292 ctx . restore ( ) ; // Restore transform
293293 } ;
294294
295295 const draw = ( e ) => {
296- if ( ! isPointerDown ) return ;
296+ if ( ! isPointerDown || ! isDrawing ) return ;
297297
298298 const canvas = canvasRef . current ;
299299 const ctx = canvas ?. getContext ( "2d" ) ;
300300 if ( ! ctx ) return ;
301301
302302 // Apply transform
303+
303304 ctx . save ( ) ;
304305 ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
305306 ctx . translate ( offset . x , offset . y ) ;
@@ -317,25 +318,121 @@ export const Canvas = () => {
317318 return ;
318319 }
319320
320- if ( ! isDrawing ) {
321- ctx . restore ( ) ;
322- return ;
323- }
321+ // --- Brush / Pen / Eraser Tools ---
322+ if (
323+ activeTool === "pen" ||
324+ activeTool === "eraser" ||
325+ activeTool . startsWith ( "brush-" )
326+ ) {
327+ ctx . lineCap = "round" ;
328+ ctx . lineJoin = "round" ;
329+ ctx . setLineDash ( [ ] ) ;
330+ ctx . shadowBlur = 0 ;
331+ ctx . globalAlpha = 1 ;
332+
333+ let color = activeColor ;
334+ let width = strokeWidth ;
335+
336+ if ( activeTool === "eraser" ) {
337+ color = "#ffffff" ;
338+ width = strokeWidth * 3 ;
339+ }
340+
341+ if ( activeTool . startsWith ( "brush-" ) ) {
342+ const brush = activeTool . split ( "-" ) [ 1 ] ;
343+ switch ( brush ) {
344+ case "dashed" : {
345+ const dashLength = strokeWidth * 4 ;
346+ const gapLength = strokeWidth * 2.5 ;
347+ ctx . setLineDash ( [ dashLength , gapLength ] ) ;
348+ ctx . lineCap = "round" ;
349+ ctx . lineJoin = "round" ;
350+
351+ ctx . strokeStyle = activeColor ;
352+ ctx . lineWidth = strokeWidth ;
353+
354+ const jitterX = x + ( Math . random ( ) - 0.5 ) * 0.5 ;
355+ const jitterY = y + ( Math . random ( ) - 0.5 ) * 0.5 ;
356+ ctx . lineTo ( jitterX , jitterY ) ;
357+ ctx . stroke ( ) ;
358+ break ;
359+ }
360+
361+ case "paint" :
362+ ctx . shadowColor = color ;
363+ ctx . shadowBlur = 12 ;
364+ ctx . globalAlpha = 0.5 + Math . random ( ) * 0.2 ;
365+ width = strokeWidth * 2 ;
366+ break ;
367+ case "crayon" :
368+ ctx . globalAlpha = 0.8 ;
369+ ctx . shadowBlur = 5 ;
370+ for ( let i = 0 ; i < 4 ; i ++ ) {
371+ const jitterX = x + ( Math . random ( ) - 0.5 ) * 1.5 ;
372+ const jitterY = y + ( Math . random ( ) - 0.5 ) * 1.5 ;
373+ ctx . lineTo ( jitterX , jitterY ) ;
374+ }
375+ break ;
376+ case "oil-pastel" : {
377+ console . log ( "this is oil" )
378+ ctx . setLineDash ( [ ] ) ;
379+ ctx . lineCap = "round" ;
380+ ctx . lineJoin = "round" ;
381+
382+ const steps = 10 ;
383+ for ( let i = 0 ; i < steps ; i ++ ) {
384+ const jitterX = x + ( Math . random ( ) - 0.5 ) * 5 ;
385+ const jitterY = y + ( Math . random ( ) - 0.5 ) * 5 ;
386+ const jitterWidth = strokeWidth * ( 0.8 + Math . random ( ) * 0.6 ) ;
387+ const opacity = 0.1 + Math . random ( ) * 0.15 ;
388+ const color = tinycolor ( activeColor )
389+ . brighten ( ( Math . random ( ) - 0.5 ) * 8 )
390+ . setAlpha ( opacity )
391+ . toRgbString ( ) ;
392+
393+ ctx . strokeStyle = color ;
394+ ctx . lineWidth = jitterWidth ;
395+
396+ ctx . beginPath ( ) ;
397+ ctx . moveTo (
398+ startPoint . current . x + ( Math . random ( ) - 0.5 ) * 3 ,
399+ startPoint . current . y + ( Math . random ( ) - 0.5 ) * 3
400+ ) ;
401+ ctx . lineTo ( jitterX , jitterY ) ;
402+ ctx . stroke ( ) ;
403+ }
404+ ctx . shadowColor = activeColor ;
405+ ctx . shadowBlur = 2 ;
406+ ctx . globalAlpha = 0.7 ;
407+ ctx . lineWidth = strokeWidth * 1.5 ;
408+ ctx . beginPath ( ) ;
409+ ctx . moveTo ( startPoint . current . x , startPoint . current . y ) ;
410+ ctx . lineTo ( x , y ) ;
411+ ctx . stroke ( ) ;
412+ ctx . shadowBlur = 0 ;
413+ ctx . globalAlpha = 1 ;
414+ break ;
415+ }
416+
417+ default :
418+ ctx . setLineDash ( [ ] ) ;
419+ }
420+ }
421+
422+ ctx . strokeStyle = color ;
423+ ctx . lineWidth = width ;
324424
325- // --- Handle Drawing ---
326- if ( activeTool === "pen" || activeTool === "eraser" ) {
327- ctx . strokeStyle = activeTool === "eraser" ? "#ffffff" : activeColor ;
328- ctx . lineWidth = activeTool === "eraser" ? strokeWidth * 3 : strokeWidth ;
329425 ctx . lineTo ( x , y ) ;
330426 ctx . stroke ( ) ;
427+
331428 if ( joined && socket )
332429 socket . emit ( "draw" , {
333430 roomId,
334- x, // Send WORLD coordinates
335- y, // Send WORLD coordinates
431+ x,
432+ y,
336433 type : "move" ,
337- color : activeColor ,
338- width : strokeWidth ,
434+ color,
435+ width,
339436 tool : activeTool ,
340437 } ) ;
341438 } else if ( activeTool === "line" || activeTool === "rectangle" ) {
@@ -459,7 +556,7 @@ export const Canvas = () => {
459556 return "cursor-crosshair" ;
460557 } ;
461558
462- const handleExport = ( format ) => {
559+ const handleExport = ( format ) => {
463560 const canvas = canvasRef . current ;
464561 if ( ! canvas ) return ;
465562
@@ -485,7 +582,7 @@ export const Canvas = () => {
485582 }
486583
487584 case "svg" : {
488- const svgCtx = new C2S ( canvas . width , canvas . height ) ;
585+ const svgCtx = new C2S ( canvas . width , canvas . height ) ;
489586 const svgData = svgCtx . getSerializedSvg ( ) ;
490587 const blob = new Blob ( [ svgData ] , { type : "image/svg+xml" } ) ;
491588 const link = document . createElement ( "a" ) ;
0 commit comments