@@ -669,6 +669,134 @@ class Activity {
669669 }
670670 } ;
671671
672+ /**
673+ * Ensures blocks stay within canvas boundaries when resized.
674+ */
675+ function repositionBlocks ( activity ) {
676+ const blocks = Object . values ( activity . blocks . blockList ) ;
677+ const canvasWidth = window . innerWidth ;
678+
679+ blocks . forEach ( block => {
680+
681+ // Store the initial position before any resizing
682+ if ( ! block . initialPosition ) {
683+ block . initialPosition = { x : block . container . x , y : block . container . y } ;
684+ }
685+
686+ //optimizing for tablets
687+ if ( canvasWidth < 768 && ! block . beforeMobilePosition ) {
688+ block . beforeMobilePosition = { x : block . container . x , y : block . container . y } ;
689+ }
690+
691+ if ( canvasWidth >= 768 && block . beforeMobilePosition ) {
692+ block . container . x = block . beforeMobilePosition . x ;
693+ block . container . y = block . beforeMobilePosition . y ;
694+ }
695+
696+ // Store position when the screen width first goes below 600px
697+ if ( canvasWidth < 600 && ! block . before600pxPosition ) {
698+ block . before600pxPosition = { x : block . container . x , y : block . container . y } ;
699+ }
700+
701+ // Restore position when resizing back above 600px
702+ if ( canvasWidth >= 600 && block . before600pxPosition ) {
703+ block . container . x = block . before600pxPosition . x ;
704+ block . container . y = block . before600pxPosition . y ;
705+ }
706+
707+ //optimizing for mobile
708+ if ( canvasWidth < 480 && ! block . beforeSmallPhonePosition ) {
709+ block . beforeSmallPhonePosition = { x : block . container . x , y : block . container . y } ;
710+ }
711+
712+
713+ if ( canvasWidth >= 480 && block . beforeSmallPhonePosition ) {
714+ block . container . x = block . beforeSmallPhonePosition . x ;
715+ block . container . y = block . beforeSmallPhonePosition . y ;
716+ }
717+
718+ //ensuring that the blocks are within the horizontal boundary
719+ if ( block . container . x + block . width > canvasWidth ) {
720+ block . container . x = canvasWidth - block . width - 10 ;
721+ }
722+ } ) ;
723+
724+ activity . _findBlocks ( ) ;
725+ }
726+
727+ //if any window resize event occurs:
728+ window . addEventListener ( "resize" , ( ) => repositionBlocks ( this ) ) ;
729+
730+ /**
731+ * Finds and organizes blocks within the workspace.
732+ * Arranges blocks in grid format on wide screens and vertically on narrow screens.
733+ */
734+ this . _findBlocks = ( ) => {
735+ if ( ! this . blocks . visible ) {
736+ this . _changeBlockVisibility ( ) ;
737+ }
738+
739+ this . blocks . activeBlock = null ;
740+ hideDOMLabel ( ) ;
741+ this . blocks . showBlocks ( ) ;
742+ this . blocksContainer . x = 0 ;
743+ this . blocksContainer . y = 0 ;
744+
745+ const screenWidth = window . innerWidth ;
746+ const isNarrowScreen = screenWidth < 600 ;
747+ const minColumnWidth = 400 ;
748+ let numColumns = isNarrowScreen ? 1 : Math . floor ( screenWidth / minColumnWidth ) ;
749+
750+ let toppos = this . auxToolbar . style . display === "block" ? 90 + this . toolbarHeight : 90 ;
751+ let x = isNarrowScreen ? Math . floor ( screenWidth / 2 ) : Math . floor ( this . canvas . width / 4 ) ;
752+ let y = Math . floor ( toppos * this . turtleBlocksScale ) ;
753+ let verticalSpacing = Math . floor ( 40 * this . turtleBlocksScale ) ;
754+
755+ const columnSpacing = ( screenWidth / numColumns ) * 1.2 ;
756+ const columnXPositions = Array . from ( { length : numColumns } , ( _ , i ) =>
757+ Math . floor ( i * columnSpacing + columnSpacing / 2 )
758+ ) ;
759+ const columnYPositions = Array ( numColumns ) . fill ( y ) ;
760+
761+ for ( const blk in this . blocks . blockList ) {
762+ if ( ! this . blocks . blockList [ blk ] . trash ) {
763+
764+ // Store original position only once
765+ if ( ! myBlock . originalPosition ) {
766+ myBlock . originalPosition = { x : myBlock . container . x , y : myBlock . container . y } ;
767+ }
768+
769+ const myBlock = this . blocks . blockList [ blk ] ;
770+ if ( myBlock . connections [ 0 ] === null ) {
771+ if ( isNarrowScreen ) {
772+ const dx = x - myBlock . container . x ;
773+ const dy = y - myBlock . container . y ;
774+ this . blocks . moveBlockRelative ( blk , dx , dy ) ;
775+ y += myBlock . height + verticalSpacing ;
776+ } else {
777+ let minYIndex = columnYPositions . indexOf ( Math . min ( ...columnYPositions ) ) ;
778+ const dx = columnXPositions [ minYIndex ] - myBlock . container . x ;
779+ const dy = columnYPositions [ minYIndex ] - myBlock . container . y ;
780+ this . blocks . moveBlockRelative ( blk , dx , dy ) ;
781+ columnYPositions [ minYIndex ] += myBlock . height + verticalSpacing ;
782+ }
783+ }
784+ }
785+ }
786+
787+ repositionBlocks ( this ) ;
788+ this . setHomeContainers ( false ) ;
789+ this . boundary . hide ( ) ;
790+
791+ for ( let turtle = 0 ; turtle < this . turtles . turtleList . length ; turtle ++ ) {
792+ const savedPenState = this . turtles . turtleList [ turtle ] . painter . penState ;
793+ this . turtles . turtleList [ turtle ] . painter . penState = false ;
794+ this . turtles . turtleList [ turtle ] . painter . doSetXY ( 0 , 0 ) ;
795+ this . turtles . turtleList [ turtle ] . painter . doSetHeading ( 0 ) ;
796+ this . turtles . turtleList [ turtle ] . painter . penState = savedPenState ;
797+ }
798+ } ;
799+
672800 /**
673801 * Finds and organizes blocks within the workspace.
674802 * Blocks are positioned based on their connections and availability within the canvas area.
0 commit comments