mirror of
https://github.com/YuzuZensai/Pien-Studio.git
synced 2026-09-02 14:18:35 +00:00
✨ feat: more tests, refactored
This commit is contained in:
@@ -7,6 +7,11 @@ type FaceBlurPreview = {
|
||||
effects: LayerEffect[];
|
||||
};
|
||||
|
||||
type FaceSelectionState = {
|
||||
key: string;
|
||||
indices: number[];
|
||||
};
|
||||
|
||||
type UseFaceBlurWorkflowOptions = {
|
||||
selectedLayer: Layer | null;
|
||||
faceDetectionsLayerId: string | null;
|
||||
@@ -20,8 +25,7 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
const [blurMethod, setBlurMethod] = React.useState<FaceBlurMethod>("gaussian");
|
||||
const [blurAmount, setBlurAmount] = React.useState(14);
|
||||
const [censorColor, setCensorColor] = React.useState("#111111");
|
||||
const [selectedFaceIndices, setSelectedFaceIndices] = React.useState<number[]>([]);
|
||||
const [faceBlurPreview, setFaceBlurPreview] = React.useState<FaceBlurPreview | null>(null);
|
||||
const [faceSelection, setFaceSelection] = React.useState<FaceSelectionState | null>(null);
|
||||
const hasDetectableSelection = Boolean(selectedLayer && selectedLayer.type === "raster" && faceDetectionsLayerId === selectedLayer.id);
|
||||
|
||||
const faceBlurEffect = React.useMemo(
|
||||
@@ -29,6 +33,15 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
[selectedLayer?.effects],
|
||||
);
|
||||
|
||||
const selectionKey = `${selectedLayer?.id ?? "none"}:${faceDetectionsLayerId ?? "none"}:${faceDetections.length}:${faceBlurEffect ? "effect" : "empty"}`;
|
||||
|
||||
const defaultSelectedFaceIndices = React.useMemo(() => {
|
||||
if (!hasDetectableSelection || faceBlurEffect) return [];
|
||||
return faceDetections.map((_, index) => index);
|
||||
}, [faceDetections, faceBlurEffect, hasDetectableSelection]);
|
||||
|
||||
const selectedFaceIndices = faceSelection?.key === selectionKey ? faceSelection.indices : defaultSelectedFaceIndices;
|
||||
|
||||
const buildBlurRegions = React.useCallback(
|
||||
(indices: number[]) => {
|
||||
if (!selectedLayer || selectedLayer.type !== "raster") return [];
|
||||
@@ -56,14 +69,18 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
);
|
||||
|
||||
const toggleFaceIndex = React.useCallback((index: number) => {
|
||||
setSelectedFaceIndices((prev) => (prev.includes(index) ? prev.filter((item) => item !== index) : [...prev, index]));
|
||||
}, []);
|
||||
setFaceSelection((prev) => {
|
||||
const current = prev?.key === selectionKey ? prev.indices : defaultSelectedFaceIndices;
|
||||
const indices = current.includes(index) ? current.filter((item) => item !== index) : [...current, index];
|
||||
return { key: selectionKey, indices };
|
||||
});
|
||||
}, [defaultSelectedFaceIndices, selectionKey]);
|
||||
|
||||
const clearBlur = React.useCallback(() => {
|
||||
if (!selectedLayer) return;
|
||||
removeLayerEffect(selectedLayer.id, "face-blur");
|
||||
setFaceBlurPreview(null);
|
||||
}, [selectedLayer, removeLayerEffect]);
|
||||
setFaceSelection({ key: selectionKey, indices: [] });
|
||||
}, [removeLayerEffect, selectedLayer, selectionKey]);
|
||||
|
||||
const blurFaces = React.useCallback(
|
||||
(indices: number[]) => {
|
||||
@@ -78,41 +95,21 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
regions,
|
||||
censorColor,
|
||||
});
|
||||
setSelectedFaceIndices([]);
|
||||
setFaceBlurPreview(null);
|
||||
setFaceSelection({ key: selectionKey, indices: [] });
|
||||
},
|
||||
[blurAmount, blurMethod, buildBlurRegions, censorColor, faceDetections.length, faceDetectionsLayerId, selectedLayer, setLayerEffect],
|
||||
[blurAmount, blurMethod, buildBlurRegions, censorColor, faceDetections.length, faceDetectionsLayerId, selectedLayer, selectionKey, setLayerEffect],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!hasDetectableSelection) {
|
||||
setSelectedFaceIndices((prev) => (prev.length === 0 ? prev : []));
|
||||
setFaceBlurPreview(null);
|
||||
return;
|
||||
}
|
||||
if (faceBlurEffect) {
|
||||
setSelectedFaceIndices((prev) => (prev.length === 0 ? prev : []));
|
||||
return;
|
||||
}
|
||||
setSelectedFaceIndices((prev) => {
|
||||
const next = faceDetections.map((_, i) => i);
|
||||
if (prev.length === next.length && prev.every((value, index) => value === next[index])) return prev;
|
||||
return next;
|
||||
});
|
||||
}, [faceDetections, hasDetectableSelection, faceBlurEffect]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const faceBlurPreview = React.useMemo<FaceBlurPreview | null>(() => {
|
||||
if (!hasDetectableSelection || !selectedLayer || selectedLayer.type !== "raster") {
|
||||
setFaceBlurPreview(null);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (selectedFaceIndices.length === 0) {
|
||||
setFaceBlurPreview(null);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
setFaceBlurPreview({
|
||||
return {
|
||||
layerId: selectedLayer.id,
|
||||
effects: [{
|
||||
kind: "face-blur",
|
||||
@@ -122,7 +119,7 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
regions: buildBlurRegions(selectedFaceIndices),
|
||||
censorColor,
|
||||
}],
|
||||
});
|
||||
};
|
||||
}, [blurAmount, blurMethod, buildBlurRegions, censorColor, hasDetectableSelection, selectedFaceIndices, selectedLayer]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -32,7 +32,6 @@ type SelectedImageLayer = {
|
||||
|
||||
type UseFaceDetectionOptions = {
|
||||
tool: EditorToolId;
|
||||
selectedLayerId: string | null;
|
||||
selectedImageLayer: SelectedImageLayer | null;
|
||||
activeLayerStillSelected: (layerId: string) => boolean;
|
||||
};
|
||||
@@ -40,7 +39,6 @@ type UseFaceDetectionOptions = {
|
||||
export function useFaceDetection(options: UseFaceDetectionOptions) {
|
||||
const {
|
||||
tool,
|
||||
selectedLayerId,
|
||||
selectedImageLayer,
|
||||
activeLayerStillSelected,
|
||||
} = options;
|
||||
@@ -63,6 +61,7 @@ export function useFaceDetection(options: UseFaceDetectionOptions) {
|
||||
(status: "idle" | "detecting" | "unsupported" = "idle") => {
|
||||
setFaceDetections((prev) => (prev.length === 0 ? prev : []));
|
||||
setFaceDetectionsLayerId((prev) => (prev === null ? prev : null));
|
||||
setFacePreviews((prev) => (prev.length === 0 ? prev : []));
|
||||
setFaceStatus((prev) => (prev === status ? prev : status));
|
||||
},
|
||||
[],
|
||||
@@ -115,18 +114,6 @@ export function useFaceDetection(options: UseFaceDetectionOptions) {
|
||||
tool,
|
||||
]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (tool !== "face") {
|
||||
setFaceDetections([]);
|
||||
setFaceDetectionsLayerId(null);
|
||||
setFacePreviews([]);
|
||||
return;
|
||||
}
|
||||
setFaceDetections([]);
|
||||
setFaceDetectionsLayerId(null);
|
||||
setFacePreviews([]);
|
||||
}, [tool, selectedLayerId]);
|
||||
|
||||
React.useEffect(() => {
|
||||
let canceled = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user