From b473bfdc5dd61963ccaf81f19ac27e482c9ecac2 Mon Sep 17 00:00:00 2001 From: jonvdveen <196496658+jonvdveen@users.noreply.github.com> Date: Thu, 2 Jul 2026 21:23:57 -0600 Subject: [PATCH] feat: resolution condition for workflow IF/SWITCH nodes (megapixels, short/long edge) Adds a "Resolution" condition type filtering assets by image dimensions, useful for isolating low-resolution images for cleanup or selecting high-resolution ones. Three metrics with optional min/max bounds: - Megapixels (width x height / 1e6, fractional values allowed) - Short edge in pixels (LEAST of width/height) - Long edge in pixels (GREATEST of width/height) Short/long edge are orientation-agnostic, so a 4000x3000 landscape and a 3000x4000 portrait are treated identically. Uses the exifImageWidth/ exifImageHeight columns on asset_exif, which the condition queries already join; assets without recorded dimensions never match. Co-Authored-By: Claude Fable 5 --- .../workflows/config/ConditionEditor.tsx | 20 +++++++++++++++++++ .../workflows/nodes/conditionSummary.ts | 11 ++++++++++ src/lib/workflow/conditionBuilder.ts | 15 ++++++++++++++ src/types/workflow.d.ts | 2 +- 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/components/workflows/config/ConditionEditor.tsx b/src/components/workflows/config/ConditionEditor.tsx index 084e63b..edd15da 100644 --- a/src/components/workflows/config/ConditionEditor.tsx +++ b/src/components/workflows/config/ConditionEditor.tsx @@ -27,6 +27,7 @@ const conditionTypeLabels: Record = { asset_type: "Asset Type", iso_range: "ISO Range", focal_length: "Focal Length", + resolution: "Resolution", rating: "Rating", is_favorited: "Favorited", not_in_album: "Not in Any Album", @@ -192,6 +193,25 @@ function ConditionFields({ condition, onChange }: { condition: ICondition; onCha onChange({ ...condition, max: parseInt(e.target.value) || undefined })} /> ); + case "resolution": { + const unit = (condition.metric || "megapixels") === "megapixels" ? "MP" : "px"; + return ( +
+ +
+ onChange({ ...condition, min: e.target.value === "" ? undefined : parseFloat(e.target.value) })} /> + onChange({ ...condition, max: e.target.value === "" ? undefined : parseFloat(e.target.value) })} /> +
+
+ ); + } case "is_favorited": return (