Refactor SwapPositions component for better maintainability and performance

This commit is contained in:
2025-03-22 15:57:53 +01:00
parent 577d5b15c8
commit ba304f0047
+118 -33
View File
@@ -3,49 +3,134 @@ import { ArrowSwapRegular } from "@fluentui/react-icons";
import { useStatusContext } from "./App";
import { useCommonStyles } from "./commonStyles";
import ActionButton from "./ActionButton";
import { getErrorMessage } from "../types/office-types";
// Position properties to load and swap
const POSITION_PROPERTIES = ["left", "top"];
// Shape position data interface
interface ShapePosition {
left: number;
top: number;
}
export const SwapPositions: React.FC = () => {
const styles = useCommonStyles();
const { setStatusMessage, setStatusType } = useStatusContext();
const swapPositionsOfTwoSelectedObjects = async () => {
await PowerPoint.run(async (context) => {
// Get the selected shapes
const shapes = context.presentation.getSelectedShapes();
shapes.load("items/count");
await context.sync();
/**
* Validates that exactly two shapes are selected
* @param shapes The collection of selected shapes
* @returns True if validation passes, false otherwise
*/
const validateShapeSelection = (shapes: PowerPoint.ShapeScopedCollection): boolean => {
if (shapes.items.length !== 2) {
setStatusMessage("Please select exactly two shapes to swap their positions.");
setStatusType("warning");
return false;
}
return true;
};
// Check if exactly two shapes are selected
if (shapes.items.length !== 2) {
setStatusMessage("Please select exactly two shapes to swap their positions.");
setStatusType("warning");
return;
}
/**
* Loads position properties from the shapes
* @param shape1 The first shape
* @param shape2 The second shape
* @param context The PowerPoint request context
* @returns The loaded shapes
*/
const loadShapePositions = async (
shape1: PowerPoint.Shape,
shape2: PowerPoint.Shape,
context: PowerPoint.RequestContext
): Promise<[PowerPoint.Shape, PowerPoint.Shape]> => {
// Load position properties for both shapes in a single batch
shape1.load(POSITION_PROPERTIES);
shape2.load(POSITION_PROPERTIES);
await context.sync();
return [shape1, shape2];
};
// Get the two shapes
const shapeObj1 = shapes.items[0];
const shapeObj2 = shapes.items[1];
// Load position properties
shapeObj1.load("left,top");
shapeObj2.load("left,top");
await context.sync();
/**
* Swaps the positions of two shapes
* @param shape1 The first shape
* @param shape2 The second shape
* @returns True if the swap was successful
*/
const swapPositions = (
shape1: PowerPoint.Shape,
shape2: PowerPoint.Shape
): boolean => {
try {
// Store the position of the first shape
const tempLeft = shapeObj1.left;
const tempTop = shapeObj1.top;
const tempPosition: ShapePosition = {
left: shape1.left,
top: shape1.top
};
// Swap positions
shapeObj1.left = shapeObj2.left;
shapeObj1.top = shapeObj2.top;
shapeObj2.left = tempLeft;
shapeObj2.top = tempTop;
shape1.left = shape2.left;
shape1.top = shape2.top;
shape2.left = tempPosition.left;
shape2.top = tempPosition.top;
await context.sync();
setStatusMessage("Positions of the two shapes have been swapped successfully.");
setStatusType("success");
});
return true;
} catch (err) {
console.error("Error swapping positions:", getErrorMessage(err));
return false;
}
};
/**
* Generates an appropriate status message based on the results
* @param success Whether the swap was successful
* @returns The formatted status message
*/
const generateStatusMessage = (success: boolean): string => {
return success
? "Positions of the two shapes have been swapped successfully."
: "Failed to swap positions. Please try again with different shapes.";
};
/**
* Main function to swap positions of two selected shapes
*/
const swapPositionsOfTwoSelectedObjects = async (): Promise<void> => {
try {
await PowerPoint.run(async (context) => {
// Get the selected shapes
const shapes = context.presentation.getSelectedShapes();
shapes.load("items");
await context.sync();
// Validate shape selection
if (!validateShapeSelection(shapes)) {
return;
}
// Get the two shapes
const [shape1, shape2] = await loadShapePositions(
shapes.items[0],
shapes.items[1],
context
);
// Swap positions
const swapSuccess = swapPositions(shape1, shape2);
// Sync changes to PowerPoint
await context.sync();
// Update status message
const statusMessage = generateStatusMessage(swapSuccess);
setStatusMessage(statusMessage);
setStatusType(swapSuccess ? "success" : "error");
});
} catch (error) {
console.error("Error in swapPositionsOfTwoSelectedObjects:", getErrorMessage(error));
setStatusMessage(`Error: ${getErrorMessage(error)}`);
setStatusType("error");
}
};
return (
@@ -61,4 +146,4 @@ export const SwapPositions: React.FC = () => {
);
};
export default SwapPositions;
export default SwapPositions;