Now only using one status box

This commit is contained in:
2025-03-08 00:30:43 +01:00
parent ba393bac87
commit dd2561adc8
3 changed files with 139 additions and 107 deletions
+123 -15
View File
@@ -2,12 +2,34 @@ import * as React from "react";
import { useEffect, useState } from "react";
import MatchSizes from "./MatchSizes";
import MatchProperties from "./MatchProperties";
import { makeStyles, Text, Subtitle1, tokens, Theme } from "@fluentui/react-components";
import { makeStyles, Text, Subtitle1, tokens, Theme, Spinner } from "@fluentui/react-components";
import { ShapeUnionRegular, SquareRegular, InfoRegular } from "@fluentui/react-icons";
interface AppProps {
title: string;
}
export type StatusType = "info" | "success" | "warning" | "error";
export interface StatusContextType {
statusMessage: string;
setStatusMessage: (message: string) => void;
statusType: StatusType;
setStatusType: (type: StatusType) => void;
isProcessing: boolean;
setIsProcessing: (processing: boolean) => void;
}
export const StatusContext = React.createContext<StatusContextType | undefined>(undefined);
export const useStatusContext = () => {
const context = React.useContext(StatusContext);
if (context === undefined) {
throw new Error('useStatusContext must be used within a StatusProvider');
}
return context;
};
const useStyles = makeStyles({
root: {
display: "flex",
@@ -18,8 +40,35 @@ const useStyles = makeStyles({
backgroundColor: tokens.colorNeutralBackground1,
overflow: "auto",
},
statusContainer: {
marginTop: "4px",
padding: "8px 12px",
fontSize: "13px",
borderRadius: "6px",
backgroundColor: "#f3f2f1", // Light gray background
transition: "all 0.3s ease",
},
successStatus: {
backgroundColor: "#DFF6DD", // Light green background
color: "#107C10", // Green text
},
warningStatus: {
backgroundColor: "#FFF4CE", // Light yellow background
color: "#797673", // Dark gray text
},
errorStatus: {
backgroundColor: "#FDE7E9", // Light red background
color: "#A80000", // Red text
},
statusIcon: {
marginRight: "8px",
},
statusText: {
display: "flex",
alignItems: "center",
},
section: {
marginBottom: "24px",
marginBottom: "4px",
padding: "12px",
borderRadius: "8px",
backgroundColor: tokens.colorNeutralBackground2,
@@ -47,6 +96,11 @@ const App: React.FC<AppProps> = () => {
const styles = useStyles();
const [theme, setTheme] = useState<string>("light");
// Status state
const [statusMessage, setStatusMessage] = useState("");
const [statusType, setStatusType] = useState<StatusType>("info");
const [isProcessing, setIsProcessing] = useState(false);
// Check if macOS is in dark mode (would need to be expanded in production)
useEffect(() => {
// In a real implementation, we would listen to Office theme changes
@@ -54,21 +108,75 @@ const App: React.FC<AppProps> = () => {
setTheme(prefersDarkMode ? "dark" : "light");
}, []);
// Auto-clear success messages after 5 seconds
useEffect(() => {
let timer: number;
if (statusType === "success" && statusMessage) {
timer = window.setTimeout(() => {
setStatusMessage("");
}, 5000);
}
return () => {
if (timer) clearTimeout(timer);
};
}, [statusMessage, statusType]);
const getStatusIcon = () => {
switch (statusType) {
case "success":
return <ShapeUnionRegular className={styles.statusIcon} />;
case "warning":
return <SquareRegular className={styles.statusIcon} />;
case "error":
return <InfoRegular className={styles.statusIcon} />;
default:
return null;
}
};
return (
<div className={styles.root} data-theme={theme}>
<div className={styles.section}>
<Subtitle1 block className={styles.sectionTitle}>
Shape Tools
</Subtitle1>
<MatchSizes />
<div style={{ marginTop: "8px" }}></div>
<MatchProperties />
<StatusContext.Provider value={{
statusMessage,
setStatusMessage,
statusType,
setStatusType,
isProcessing,
setIsProcessing
}}>
<div className={styles.root} data-theme={theme}>
<div className={styles.section}>
<Subtitle1 block className={styles.sectionTitle}>
Shape Tools
</Subtitle1>
<MatchSizes />
<div style={{ marginTop: "8px" }}></div>
<MatchProperties />
</div>
{/* Status message area at the bottom */}
{isProcessing && (
<div className={styles.statusContainer}>
<div className={styles.statusText}>
<Spinner size="tiny" style={{ marginRight: "8px" }} />
Processing...
</div>
</div>
)}
{!isProcessing && statusMessage && (
<div className={`${styles.statusContainer} ${styles[`${statusType}Status`]}`}>
<div className={styles.statusText}>
{getStatusIcon()}
{statusMessage}
</div>
</div>
)}
<div className={styles.footer}>
<Text size={100}>Edison v1.0.0</Text>
</div>
</div>
<div className={styles.footer}>
<Text size={100}>Edison v1.0.0</Text>
</div>
</div>
</StatusContext.Provider>
);
};
+8 -46
View File
@@ -2,16 +2,12 @@ import * as React from "react";
import {
Button,
makeStyles,
Text,
Spinner,
tokens
} from "@fluentui/react-components";
import {
ColorRegular,
SquareRegular,
ShapeUnionRegular,
InfoRegular
ColorRegular
} from "@fluentui/react-icons";
import { useStatusContext } from "./App";
const useStyles = makeStyles({
container: {
@@ -62,9 +58,11 @@ const useStyles = makeStyles({
export const MatchProperties: React.FC = () => {
const styles = useStyles();
const [statusMessage, setStatusMessage] = React.useState("");
const [statusType, setStatusType] = React.useState<"info" | "success" | "warning" | "error">("info");
const [isProcessing, setIsProcessing] = React.useState(false);
const {
statusMessage, setStatusMessage,
statusType, setStatusType,
isProcessing, setIsProcessing
} = useStatusContext();
const matchPropertiesToFirstSelected = async () => {
setIsProcessing(true);
@@ -245,12 +243,7 @@ export const MatchProperties: React.FC = () => {
setStatusType("error");
}
// Auto-clear success message after 5 seconds
setTimeout(() => {
if (statusType === "success") {
setStatusMessage("");
}
}, 5000);
// Timeout is handled in App.tsx now
});
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
@@ -261,19 +254,6 @@ export const MatchProperties: React.FC = () => {
}
};
const getStatusIcon = () => {
switch (statusType) {
case "success":
return <ShapeUnionRegular className={styles.statusIcon} />;
case "warning":
return <SquareRegular className={styles.statusIcon} />;
case "error":
return <InfoRegular className={styles.statusIcon} />;
default:
return null;
}
};
return (
<div className={styles.container}>
<div className={styles.buttonGroup}>
@@ -287,24 +267,6 @@ export const MatchProperties: React.FC = () => {
Match Properties
</Button>
</div>
{isProcessing && (
<div className={styles.statusContainer}>
<div className={styles.statusText}>
<Spinner size="tiny" style={{ marginRight: "8px" }} />
Applying properties...
</div>
</div>
)}
{!isProcessing && statusMessage && (
<div className={`${styles.statusContainer} ${styles[`${statusType}Status`]}`}>
<div className={styles.statusText}>
{getStatusIcon()}
{statusMessage}
</div>
</div>
)}
</div>
);
};
+8 -46
View File
@@ -5,18 +5,15 @@ import {
Text,
Tooltip,
InfoLabel,
Spinner,
tokens,
Card
} from "@fluentui/react-components";
import {
ArrowFitInRegular,
ArrowSortDownRegular,
ArrowSortUpRegular,
SquareRegular,
ShapeUnionRegular,
InfoRegular
ArrowSortUpRegular
} from "@fluentui/react-icons";
import { useStatusContext } from "./App";
const useStyles = makeStyles({
container: {
@@ -67,9 +64,11 @@ const useStyles = makeStyles({
export const MatchSizes: React.FC = () => {
const styles = useStyles();
const [statusMessage, setStatusMessage] = React.useState("");
const [statusType, setStatusType] = React.useState<"info" | "success" | "warning" | "error">("info");
const [isProcessing, setIsProcessing] = React.useState(false);
const {
statusMessage, setStatusMessage,
statusType, setStatusType,
isProcessing, setIsProcessing
} = useStatusContext();
const matchSizeToFirstSelected = async () => {
setIsProcessing(true);
@@ -109,12 +108,7 @@ export const MatchSizes: React.FC = () => {
setStatusMessage(`Resized ${shapes.items.length - 1} shapes to match the first selected shape.`);
setStatusType("success");
// Auto-clear success message after 5 seconds
setTimeout(() => {
if (statusType === "success") {
setStatusMessage("");
}
}, 5000);
// Timeout is handled in App.tsx now
});
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
@@ -126,19 +120,6 @@ export const MatchSizes: React.FC = () => {
};
const getStatusIcon = () => {
switch (statusType) {
case "success":
return <ShapeUnionRegular className={styles.statusIcon} />;
case "warning":
return <SquareRegular className={styles.statusIcon} />;
case "error":
return <InfoRegular className={styles.statusIcon} />;
default:
return null;
}
};
return (
<div className={styles.container}>
<div className={styles.buttonGroup}>
@@ -152,25 +133,6 @@ export const MatchSizes: React.FC = () => {
Match Sizes
</Button>
</div>
{isProcessing && (
<div className={styles.statusContainer}>
<div className={styles.statusText}>
<Spinner size="tiny" style={{ marginRight: "8px" }} />
Resizing shapes...
</div>
</div>
)}
{!isProcessing && statusMessage && (
<div className={`${styles.statusContainer} ${styles[`${statusType}Status`]}`}>
<div className={styles.statusText}>
{getStatusIcon()}
{statusMessage}
</div>
</div>
)}
</div>
);
};