Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"build": "vite build",
"tauri": "tauri",
"start": "tauri dev",
"bindings:gen": "cd src-tauri && RAPIDRAW_EXPORT_BINDINGS_ONLY=1 cargo run --quiet",
"check:ipc": "./scripts/check-ipc-contract.sh",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
Expand Down
89 changes: 89 additions & 0 deletions scripts/check-ipc-contract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

backend_cmds="$TMP_DIR/backend_cmds.txt"
front_enum_cmds="$TMP_DIR/front_enum_cmds.txt"
front_literal_cmds="$TMP_DIR/front_literal_cmds.txt"
front_event_methods="$TMP_DIR/front_event_methods.txt"
backend_events="$TMP_DIR/backend_events.txt"
front_events="$TMP_DIR/front_events.txt"

rg -n "#\\[tauri::command\\]" src-tauri/src -A2 --no-heading \
| rg -o "fn [a-zA-Z0-9_]+" \
| awk '{print $2}' \
| sort -u > "$backend_cmds"

if rg -q "export enum Invokes" src/components/ui/AppProperties.tsx; then
sed -n '/export enum Invokes {/,/^}/p' src/components/ui/AppProperties.tsx \
| rg -o "'[^']+'" \
| tr -d "'" \
| sort -u > "$front_enum_cmds"
else
: > "$front_enum_cmds"
fi

if rg -q "invoke\\(\\s*['\"][^'\"]+['\"]" src --glob '!src-tauri/**'; then
rg -n "invoke\\(\\s*['\"][^'\"]+['\"]" src --glob '!src-tauri/**' -o \
| sed -E "s/.*invoke\\(\\s*['\"]([^'\"]+)['\"].*/\\1/" \
| sort -u > "$front_literal_cmds"
else
: > "$front_literal_cmds"
fi

if [[ -f src/bindings.ts ]]; then
sed -n '/}>({/,/^})/p' src/bindings.ts \
| sed -nE 's/^[[:space:]]*[A-Za-z0-9_]+:[[:space:]]*"([^"]+)".*/\1/p' \
| sort -u > "$backend_events"
else
rg --files src-tauri/src \
| xargs perl -0777 -ne 'while (/\.emit(?:_to|_filter)?\(\s*"([^"]+)"/g) { print "$1\n"; }' \
| sort -u > "$backend_events"
fi

rg --files src --glob '!src-tauri/**' \
| xargs perl -ne 'while (/(?:listen|once)\(\s*["\x27]([^"\x27]+)["\x27]/g) { print "$1\n"; } while (/events\.([A-Za-z0-9_]+)\.(?:listen|once)\s*\(/g) { print "__method__:$1\n"; }' \
| sort -u > "$front_event_methods"

grep -v '^__method__:' "$front_event_methods" > "$front_events" || true

grep '^__method__:' "$front_event_methods" | sed 's/^__method__://' | while read -r method; do
mapped="$(sed -nE "s/^[[:space:]]*${method}:[[:space:]]*\"([^\"]+)\".*/\\1/p" src/bindings.ts | head -n1)"
if [[ -n "$mapped" ]]; then
echo "$mapped" >> "$front_events"
fi
done

sort -u "$front_events" -o "$front_events"

if [[ -s "$front_enum_cmds" ]]; then
echo "=== Commands in frontend enum but missing in backend ==="
comm -23 "$front_enum_cmds" "$backend_cmds" || true
echo

echo "=== Commands in backend but missing in frontend enum ==="
comm -13 "$front_enum_cmds" "$backend_cmds" || true
echo
else
echo "=== Frontend enum command check skipped (Invokes enum removed) ==="
echo
fi

echo "=== Literal invoke commands (not enum) ==="
cat "$front_literal_cmds"
echo

echo "=== Events listened in frontend but not emitted by backend ==="
comm -23 "$front_events" "$backend_events" || true
echo

echo "=== Events emitted by backend but not listened in frontend ==="
comm -13 "$front_events" "$backend_events" || true
echo

echo "IPC contract check complete."
84 changes: 84 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ rust-version = "1.92"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tauri = { version = "2.9", features = [ "macos-private-api", "rustls-tls" ] }
tauri = { version = "2.9", features = [ "macos-private-api", "rustls-tls", "specta" ] }
tauri-plugin-dialog = "2.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down Expand Up @@ -66,6 +66,9 @@ quick-xml = { version = "0.36", features = ["serialize"] }
fuzzy-matcher = "0.3.7"
image-hdr = { version = "0.6.0", default-features = false }
mozjpeg-rs = "0.8.0"
tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] }
specta = { version = "=2.0.0-rc.22", features = ["derive", "function", "serde_json", "tokio"] }
specta-typescript = "0.0.9"

[build-dependencies]
tauri-build = { version = "2.5", features = [] }
Expand Down
8 changes: 4 additions & 4 deletions src-tauri/src/ai_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ pub fn run_u2netp_model(image: &DynamicImage, u2netp_session: &Mutex<Session>) -
Ok(final_mask)
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[derive(Serialize, Deserialize, Debug, Clone, Default, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct AiSubjectMaskParameters {
pub start_x: f64,
Expand All @@ -528,7 +528,7 @@ pub struct AiSubjectMaskParameters {
pub orientation_steps: Option<u8>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[derive(Serialize, Deserialize, Debug, Clone, Default, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct AiSkyMaskParameters {
#[serde(default)]
Expand All @@ -543,7 +543,7 @@ pub struct AiSkyMaskParameters {
pub orientation_steps: Option<u8>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[derive(Serialize, Deserialize, Debug, Clone, Default, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct AiForegroundMaskParameters {
#[serde(default)]
Expand All @@ -556,4 +556,4 @@ pub struct AiForegroundMaskParameters {
pub flip_vertical: Option<bool>,
#[serde(default)]
pub orientation_steps: Option<u8>,
}
}
9 changes: 5 additions & 4 deletions src-tauri/src/culling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tauri::{AppHandle, Emitter};

use crate::image_loader;

#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct CullingSettings {
pub similarity_threshold: u32,
Expand All @@ -19,7 +19,7 @@ pub struct CullingSettings {
pub filter_blurry: bool,
}

#[derive(Serialize, Debug, Clone)]
#[derive(Serialize, Debug, Clone, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct ImageAnalysisResult {
pub path: String,
Expand All @@ -31,14 +31,14 @@ pub struct ImageAnalysisResult {
pub height: u32,
}

#[derive(Serialize, Debug, Clone)]
#[derive(Serialize, Debug, Clone, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct CullGroup {
pub representative: ImageAnalysisResult,
pub duplicates: Vec<ImageAnalysisResult>,
}

#[derive(Serialize, Debug, Clone, Default)]
#[derive(Serialize, Debug, Clone, Default, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct CullingSuggestions {
pub similar_groups: Vec<CullGroup>,
Expand Down Expand Up @@ -181,6 +181,7 @@ fn analyze_image(
}

#[tauri::command]
#[specta::specta]
pub async fn cull_images(
paths: Vec<String>,
settings: CullingSettings,
Expand Down
Loading
Loading