Refactor SwapPositions component for better maintainability and performance
This commit is contained in:
@@ -3,49 +3,134 @@ import { ArrowSwapRegular } from "@fluentui/react-icons";
|
|||||||
import { useStatusContext } from "./App";
|
import { useStatusContext } from "./App";
|
||||||
import { useCommonStyles } from "./commonStyles";
|
import { useCommonStyles } from "./commonStyles";
|
||||||
import ActionButton from "./ActionButton";
|
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 = () => {
|
export const SwapPositions: React.FC = () => {
|
||||||
const styles = useCommonStyles();
|
const styles = useCommonStyles();
|
||||||
const { setStatusMessage, setStatusType } = useStatusContext();
|
const { setStatusMessage, setStatusType } = useStatusContext();
|
||||||
|
|
||||||
const swapPositionsOfTwoSelectedObjects = async () => {
|
/**
|
||||||
await PowerPoint.run(async (context) => {
|
* Validates that exactly two shapes are selected
|
||||||
// Get the selected shapes
|
* @param shapes The collection of selected shapes
|
||||||
const shapes = context.presentation.getSelectedShapes();
|
* @returns True if validation passes, false otherwise
|
||||||
shapes.load("items/count");
|
*/
|
||||||
await context.sync();
|
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) {
|
* Loads position properties from the shapes
|
||||||
setStatusMessage("Please select exactly two shapes to swap their positions.");
|
* @param shape1 The first shape
|
||||||
setStatusType("warning");
|
* @param shape2 The second shape
|
||||||
return;
|
* @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];
|
* Swaps the positions of two shapes
|
||||||
const shapeObj2 = shapes.items[1];
|
* @param shape1 The first shape
|
||||||
|
* @param shape2 The second shape
|
||||||
// Load position properties
|
* @returns True if the swap was successful
|
||||||
shapeObj1.load("left,top");
|
*/
|
||||||
shapeObj2.load("left,top");
|
const swapPositions = (
|
||||||
await context.sync();
|
shape1: PowerPoint.Shape,
|
||||||
|
shape2: PowerPoint.Shape
|
||||||
|
): boolean => {
|
||||||
|
try {
|
||||||
// Store the position of the first shape
|
// Store the position of the first shape
|
||||||
const tempLeft = shapeObj1.left;
|
const tempPosition: ShapePosition = {
|
||||||
const tempTop = shapeObj1.top;
|
left: shape1.left,
|
||||||
|
top: shape1.top
|
||||||
|
};
|
||||||
|
|
||||||
// Swap positions
|
// Swap positions
|
||||||
shapeObj1.left = shapeObj2.left;
|
shape1.left = shape2.left;
|
||||||
shapeObj1.top = shapeObj2.top;
|
shape1.top = shape2.top;
|
||||||
shapeObj2.left = tempLeft;
|
shape2.left = tempPosition.left;
|
||||||
shapeObj2.top = tempTop;
|
shape2.top = tempPosition.top;
|
||||||
|
|
||||||
await context.sync();
|
return true;
|
||||||
|
} catch (err) {
|
||||||
setStatusMessage("Positions of the two shapes have been swapped successfully.");
|
console.error("Error swapping positions:", getErrorMessage(err));
|
||||||
setStatusType("success");
|
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 (
|
return (
|
||||||
@@ -61,4 +146,4 @@ export const SwapPositions: React.FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SwapPositions;
|
export default SwapPositions;
|
||||||
|
|||||||
Reference in New Issue
Block a user