From 3750fa8329dcef2e17fa516461ca2258cbdd62e7 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Fri, 14 Mar 2025 15:02:22 +0400 Subject: [PATCH 1/2] removed left and right button --- .../all_spaces/widgets/space_card_widget.dart | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/pages/spaces_management/all_spaces/widgets/space_card_widget.dart b/lib/pages/spaces_management/all_spaces/widgets/space_card_widget.dart index 0a78da52..f3a476b2 100644 --- a/lib/pages/spaces_management/all_spaces/widgets/space_card_widget.dart +++ b/lib/pages/spaces_management/all_spaces/widgets/space_card_widget.dart @@ -47,18 +47,6 @@ class SpaceCardWidget extends StatelessWidget { children: [ buildSpaceContainer(index), // Build the space container if (isHovered) ...[ - PlusButtonWidget( - index: index, - direction: 'left', - offset: const Offset(-21, 20), - onButtonTap: onButtonTap, - ), - PlusButtonWidget( - index: index, - direction: 'right', - offset: const Offset(140, 20), - onButtonTap: onButtonTap, - ), PlusButtonWidget( index: index, direction: 'down', From 8c15fffd42d11e87b7c55cd0726d7a6fc32438e6 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Wed, 19 Mar 2025 12:25:37 +0400 Subject: [PATCH 2/2] duplicate --- .../widgets/community_structure_widget.dart | 175 +++++++++++------- .../helper/space_helper.dart | 30 ++- 2 files changed, 122 insertions(+), 83 deletions(-) diff --git a/lib/pages/spaces_management/all_spaces/widgets/community_structure_widget.dart b/lib/pages/spaces_management/all_spaces/widgets/community_structure_widget.dart index 56352432..70b86074 100644 --- a/lib/pages/spaces_management/all_spaces/widgets/community_structure_widget.dart +++ b/lib/pages/spaces_management/all_spaces/widgets/community_structure_widget.dart @@ -301,11 +301,18 @@ class _CommunityStructureAreaState extends State { SpaceTemplateModel? spaceModel, List? subspaces, List? tags) { setState(() { // Set the first space in the center or use passed position - Offset centerPosition = position ?? ConnectionHelper.getCenterPosition(screenSize); + Offset newPosition; + if (parentIndex != null) { + newPosition = + getBalancedChildPosition(spaces[parentIndex]); // Ensure balanced position + } else { + newPosition = position ?? ConnectionHelper.getCenterPosition(screenSize); + } + SpaceModel newSpace = SpaceModel( name: name, icon: icon, - position: centerPosition, + position: newPosition, isPrivate: false, children: [], status: SpaceStatus.newSpace, @@ -425,7 +432,7 @@ class _CommunityStructureAreaState extends State { Connection( startSpace: parent, endSpace: child, - direction: child.incomingConnection?.direction ?? "down", + direction: "down", ), ); @@ -522,6 +529,38 @@ class _CommunityStructureAreaState extends State { ); } + Offset getBalancedChildPosition(SpaceModel parent) { + int totalSiblings = parent.children.length + 1; + double totalWidth = (totalSiblings - 1) * 250; // Horizontal spacing + double startX = parent.position.dx - (totalWidth / 2); + + Offset position = Offset(startX + (parent.children.length * 250), parent.position.dy + 180); + + // Check for overlaps & adjust + while (spaces.any((s) => (s.position - position).distance < 250)) { + position = Offset(position.dx + 250, position.dy); + } + + return position; + } + + void realignTree() { + void updatePositions(SpaceModel node, double x, double y) { + node.position = Offset(x, y); + + int numChildren = node.children.length; + double childStartX = x - ((numChildren - 1) * 250) / 2; + + for (int i = 0; i < numChildren; i++) { + updatePositions(node.children[i], childStartX + (i * 250), y + 180); + } + } + + if (spaces.isNotEmpty) { + updatePositions(spaces.first, spaces.first.position.dx, spaces.first.position.dy); + } + } + void _onDuplicate(BuildContext parentContext) { final screenWidth = MediaQuery.of(context).size.width; @@ -604,29 +643,57 @@ class _CommunityStructureAreaState extends State { void _duplicateSpace(SpaceModel space) { final Map originalToDuplicate = {}; - const double horizontalGap = 200.0; - const double verticalGap = 100.0; + double horizontalGap = 250.0; // Increased spacing + double verticalGap = 180.0; // Adjusted for better visualization - SpaceModel duplicateRecursive( - SpaceModel original, Offset parentPosition, SpaceModel? duplicatedParent) { - Offset newPosition = Offset(parentPosition.dx + horizontalGap, original.position.dy); + print("🟢 Duplicating: ${space.name}"); - while (spaces.any((s) => - (s.position - newPosition).distance < horizontalGap && s.status != SpaceStatus.deleted)) { - newPosition += Offset(horizontalGap, 0); + /// **Find a new position ensuring no overlap** + Offset getBalancedChildPosition(SpaceModel parent) { + int totalSiblings = parent.children.length + 1; + double totalWidth = (totalSiblings - 1) * horizontalGap; + double startX = parent.position.dx - (totalWidth / 2); + Offset position = Offset( + startX + (parent.children.length * horizontalGap), parent.position.dy + verticalGap); + + // **Check for overlaps & adjust** + while (spaces.any((s) => (s.position - position).distance < horizontalGap)) { + position = Offset(position.dx + horizontalGap, position.dy); } + print("🔹 New position for ${parent.name}: (${position.dx}, ${position.dy})"); + return position; + } + + /// **Realign the entire tree after duplication** + void realignTree() { + void updatePositions(SpaceModel node, double x, double y) { + node.position = Offset(x, y); + print("✅ Adjusted ${node.name} to (${x}, ${y})"); + + int numChildren = node.children.length; + double childStartX = x - ((numChildren - 1) * horizontalGap) / 2; + + for (int i = 0; i < numChildren; i++) { + updatePositions(node.children[i], childStartX + (i * horizontalGap), y + verticalGap); + } + } + + if (spaces.isNotEmpty) { + print("🔄 Realigning tree..."); + updatePositions(spaces.first, spaces.first.position.dx, spaces.first.position.dy); + } + } + + /// **Recursive duplication logic** + SpaceModel duplicateRecursive(SpaceModel original, SpaceModel? duplicatedParent) { + Offset newPosition = duplicatedParent == null + ? Offset(original.position.dx + horizontalGap, original.position.dy) + : getBalancedChildPosition(duplicatedParent); + final duplicatedName = SpaceHelper.generateUniqueSpaceName(original.name, spaces); - - final List? duplicatedSubspaces; - final List? duplicatedTags; - if (original.spaceModel != null) { - duplicatedTags = []; - duplicatedSubspaces = []; - } else { - duplicatedTags = original.tags; - duplicatedSubspaces = original.subspaces; - } + print( + "🟡 Duplicating ${original.name} → ${duplicatedName} at (${newPosition.dx}, ${newPosition.dy})"); final duplicated = SpaceModel( name: duplicatedName, @@ -637,12 +704,10 @@ class _CommunityStructureAreaState extends State { status: SpaceStatus.newSpace, parent: duplicatedParent, spaceModel: original.spaceModel, - subspaces: duplicatedSubspaces, - tags: duplicatedTags, + subspaces: original.subspaces, + tags: original.tags, ); - originalToDuplicate[original] = duplicated; - setState(() { spaces.add(duplicated); _updateNodePosition(duplicated, duplicated.position); @@ -651,60 +716,42 @@ class _CommunityStructureAreaState extends State { final newConnection = Connection( startSpace: duplicatedParent, endSpace: duplicated, - direction: original.incomingConnection?.direction ?? 'down', + direction: "down", ); connections.add(newConnection); duplicated.incomingConnection = newConnection; duplicatedParent.addOutgoingConnection(newConnection); + duplicatedParent.children.add(duplicated); + print("🔗 Created connection: ${duplicatedParent.name} → ${duplicated.name}"); } - if (original.parent != null && duplicatedParent == null) { - final originalParent = original.parent!; - final duplicatedParent = originalToDuplicate[originalParent] ?? originalParent; - - final parentConnection = Connection( - startSpace: duplicatedParent, - endSpace: duplicated, - direction: original.incomingConnection?.direction ?? "down", - ); - - connections.add(parentConnection); - duplicated.incomingConnection = parentConnection; - duplicatedParent.addOutgoingConnection(parentConnection); - } + // **Recalculate the whole tree to avoid overlaps** + realignTree(); }); - final childrenWithDownDirection = original.children - .where((child) => - child.incomingConnection?.direction == "down" && child.status != SpaceStatus.deleted) - .toList(); - - Offset childStartPosition = childrenWithDownDirection.length == 1 - ? duplicated.position - : newPosition + Offset(0, verticalGap); - - for (final child in original.children) { - final isDownDirection = child.incomingConnection?.direction == "down" ?? false; - - if (isDownDirection && childrenWithDownDirection.length == 1) { - childStartPosition = duplicated.position + Offset(0, verticalGap); - } else if (!isDownDirection) { - childStartPosition = duplicated.position + Offset(horizontalGap, 0); - } - - final duplicatedChild = duplicateRecursive(child, childStartPosition, duplicated); - duplicated.children.add(duplicatedChild); - childStartPosition += Offset(0, verticalGap); + // Recursively duplicate children + for (var child in original.children) { + duplicateRecursive(child, duplicated); } return duplicated; } + /// **Handle root duplication** if (space.parent == null) { - duplicateRecursive(space, space.position, null); + print("🟠 Duplicating root node: ${space.name}"); + SpaceModel duplicatedRoot = duplicateRecursive(space, null); + + setState(() { + spaces.add(duplicatedRoot); + realignTree(); + }); + + print("✅ Root duplication successful: ${duplicatedRoot.name}"); } else { - final duplicatedParent = originalToDuplicate[space.parent!] ?? space.parent!; - duplicateRecursive(space, space.position, duplicatedParent); + duplicateRecursive(space, space.parent); } + + print("🟢 Finished duplication process for: ${space.name}"); } } diff --git a/lib/pages/spaces_management/helper/space_helper.dart b/lib/pages/spaces_management/helper/space_helper.dart index 126306cd..4049eb7e 100644 --- a/lib/pages/spaces_management/helper/space_helper.dart +++ b/lib/pages/spaces_management/helper/space_helper.dart @@ -2,8 +2,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_m import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; class SpaceHelper { - static SpaceModel? findSpaceByUuid( - String? uuid, List communities) { + static SpaceModel? findSpaceByUuid(String? uuid, List communities) { for (var community in communities) { for (var space in community.spaces) { if (space.uuid == uuid) return space; @@ -12,8 +11,7 @@ class SpaceHelper { return null; } - static SpaceModel? findSpaceByInternalId( - String? internalId, List spaces) { + static SpaceModel? findSpaceByInternalId(String? internalId, List spaces) { if (internalId != null) { for (var space in spaces) { if (space.internalId == internalId) return space; @@ -23,8 +21,7 @@ class SpaceHelper { return null; } - static String generateUniqueSpaceName( - String originalName, List spaces) { + static String generateUniqueSpaceName(String originalName, List spaces) { final baseName = originalName.replaceAll(RegExp(r'\(\d+\)$'), '').trim(); int maxNumber = 0; @@ -54,13 +51,10 @@ class SpaceHelper { return space == selectedSpace || selectedSpace.parent?.internalId == space.internalId || - selectedSpace.children - ?.any((child) => child.internalId == space.internalId) == - true; + selectedSpace.children?.any((child) => child.internalId == space.internalId) == true; } - static bool isNameConflict( - String value, SpaceModel? parentSpace, SpaceModel? editSpace) { + static bool isNameConflict(String value, SpaceModel? parentSpace, SpaceModel? editSpace) { final siblings = parentSpace?.children .where((child) => child.internalId != editSpace?.internalId) .toList() ?? @@ -71,19 +65,17 @@ class SpaceHelper { .toList() ?? []; - final editSiblingConflict = - editSiblings.any((child) => child.name == value); + final editSiblingConflict = editSiblings.any((child) => child.name == value); final siblingConflict = siblings.any((child) => child.name == value); - final parentConflict = parentSpace?.name == value && - parentSpace?.internalId != editSpace?.internalId; + final parentConflict = + parentSpace?.name == value && parentSpace?.internalId != editSpace?.internalId; - final parentOfEditSpaceConflict = editSpace?.parent?.name == value && - editSpace?.parent?.internalId != editSpace?.internalId; + final parentOfEditSpaceConflict = + editSpace?.parent?.name == value && editSpace?.parent?.internalId != editSpace?.internalId; - final childConflict = - editSpace?.children.any((child) => child.name == value) ?? false; + final childConflict = editSpace?.children.any((child) => child.name == value) ?? false; return siblingConflict || parentConflict ||