From 2df18869e5377fac4c45aa0277881b5a246fddcf Mon Sep 17 00:00:00 2001 From: John Costa Date: Wed, 26 Feb 2025 21:27:43 +0000 Subject: [PATCH] chore: running format --- frontend/biome.json | 20 +- frontend/bun.lockb | Bin 113120 -> 113507 bytes frontend/package.json | 73 ++++---- frontend/postcss.config.js | 8 +- frontend/src-tauri/capabilities/default.json | 20 +- frontend/src-tauri/src/lib.rs | 71 ++++---- frontend/src-tauri/tauri.conf.json | 56 +++--- frontend/src/App.tsx | 182 +++++++++---------- frontend/src/components/FolderPicker.tsx | 76 ++++---- frontend/src/components/ImageViewer.tsx | 54 +++--- frontend/src/index.css | 28 +-- frontend/tailwind.config.js | 24 +-- frontend/tsconfig.json | 44 ++--- frontend/tsconfig.node.json | 16 +- frontend/vite.config.ts | 54 +++--- 15 files changed, 362 insertions(+), 364 deletions(-) diff --git a/frontend/biome.json b/frontend/biome.json index decb4ed..f8702e4 100644 --- a/frontend/biome.json +++ b/frontend/biome.json @@ -1,12 +1,12 @@ { - "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", - "organizeImports": { - "enabled": true - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true - } - } + "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + } } diff --git a/frontend/bun.lockb b/frontend/bun.lockb index d69237e6558f6fc863a4140e02ac7cf98527f3c3..66c8f4ec506356151f30af38822facd7c79cb34e 100755 GIT binary patch delta 19164 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 `x3EJiE;gtDH0oalyE!0d(yM4Cyz_0`K0 zS^cmE{$mNaa~X&Z{AbsaNU27a8bQ5&wZ;MLd4czp7Is`D4`yBh??A@O6}`3D{*QUE zhW3YYuAruyVB6~cxK#bE2|tMn=tLSD(4|Qy&wsso#%*+An08BTY*Dw*+j`>9o_F?W zolEz%@uK|z++~}+#JB;NYsO>soZ>4D7cTEFpoo=)E_24V`3rvT&r0t%^fro!lq$vU z0q7HBpM3b*3G>dBZYeOayL~mIo{CB+m>MUFUr>iBAW<|O$ih1Q^E>&!Z$%@vT+ABC zg2;Rftv6F$qH655j;w{}Hvf8bB5IC~)}g-R;C6m+zcJnrk2RZB0_LpTOAvr&QSBA#97C&kYLwT@y%fLjM`ieF(|pZ85h|-qA(fj(@AjxqRRi5ih4sZn#R8gxYzo@ z&HsuVvsg7jy<@&1tWYp%KbgG6%pthn#*Jj7q0BqVD_Ofu?>71B#0ATyv_!5j?blfg zq%=f7@6Fu#@%!#4n^KB)uMn0j#vre+@efW?KKiQVyqre%>KfJCQ}u2Ym3W$Q(bgxc zxHFUuq+f<1!`LKW<3AM44!T^h@?PNAY8C1aU-idvxXERhxI2u6`5OP?VD#G^zO)py z83@JBA^4Gsr$iz&1zl1s94Q!jO*oAIXb{uy-EYD+`rsmnIT1=O^7np4&884-yK(LITga*J`ddD>TH63%h2orx`cDzOEu_ zI17t1{@uZtvJMYlx%F+T3x4&5Q8AM74-xWaos2o(Zeh#n6!#Hg^Kf*v@h=p7pFDD| zc;7O-TBE8`nR$C(pESvm_kGJhmXAN$`I)mn!D delta 19056 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 diff --git a/frontend/package.json b/frontend/package.json index 68a9eed..a904fae 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,38 +1,39 @@ { - "name": "haystack", - "version": "0.1.0", - "description": "", - "type": "module", - "scripts": { - "start": "vite", - "dev": "vite", - "build": "vite build", - "serve": "vite preview", - "tauri": "tauri", - "lint": "bunx @biomejs/biome lint .", - "format": "bunx @biomejs/biome format . --write" - }, - "license": "MIT", - "dependencies": { - "@kobalte/core": "^0.13.9", - "@kobalte/tailwindcss": "^0.9.0", - "@tabler/icons-solidjs": "^3.30.0", - "@tauri-apps/api": "^2", - "@tauri-apps/plugin-dialog": "~2", - "@tauri-apps/plugin-opener": "^2", - "clsx": "^2.1.1", - "solid-js": "^1.9.3", - "tailwind-scrollbar-hide": "^2.0.0" - }, - "devDependencies": { - "@biomejs/biome": "^1.9.4", - "@tauri-apps/cli": "^2", - "autoprefixer": "^10.4.20", - "postcss": "^8.5.3", - "postcss-cli": "^11.0.0", - "tailwindcss": "3.4.0", - "typescript": "~5.6.2", - "vite": "^6.0.3", - "vite-plugin-solid": "^2.11.0" - } + "name": "haystack", + "version": "0.1.0", + "description": "", + "type": "module", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "tauri": "tauri", + "lint": "bunx @biomejs/biome lint .", + "format": "bunx @biomejs/biome format . --write" + }, + "license": "MIT", + "dependencies": { + "@kobalte/core": "^0.13.9", + "@kobalte/tailwindcss": "^0.9.0", + "@tabler/icons-solidjs": "^3.30.0", + "@tauri-apps/api": "^2", + "@tauri-apps/plugin-dialog": "~2", + "@tauri-apps/plugin-opener": "^2", + "clsx": "^2.1.1", + "solid-js": "^1.9.3", + "tailwind-scrollbar-hide": "^2.0.0", + "valibot": "^1.0.0-rc.2" + }, + "devDependencies": { + "@biomejs/biome": "^1.9.4", + "@tauri-apps/cli": "^2", + "autoprefixer": "^10.4.20", + "postcss": "^8.5.3", + "postcss-cli": "^11.0.0", + "tailwindcss": "3.4.0", + "typescript": "~5.6.2", + "vite": "^6.0.3", + "vite-plugin-solid": "^2.11.0" + } } diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index 2aa7205..7b75c83 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -1,6 +1,6 @@ export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, }; diff --git a/frontend/src-tauri/capabilities/default.json b/frontend/src-tauri/capabilities/default.json index e8480e0..d8e24c2 100644 --- a/frontend/src-tauri/capabilities/default.json +++ b/frontend/src-tauri/capabilities/default.json @@ -1,12 +1,12 @@ { - "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "Capability for the main window", - "windows": ["main"], - "permissions": [ - "core:default", - "opener:default", - "dialog:default", - "core:window:allow-start-dragging" - ] + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "core:default", + "opener:default", + "dialog:default", + "core:window:allow-start-dragging" + ] } diff --git a/frontend/src-tauri/src/lib.rs b/frontend/src-tauri/src/lib.rs index 1d4a06c..3920ce6 100644 --- a/frontend/src-tauri/src/lib.rs +++ b/frontend/src-tauri/src/lib.rs @@ -1,14 +1,13 @@ -use std::path::PathBuf; +use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _}; use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher}; -use tauri::Emitter; -use std::sync::mpsc::channel; use std::fs; -use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64}; -use std::sync::Mutex; +use std::path::PathBuf; +use std::sync::mpsc::channel; use std::sync::Arc; +use std::sync::Mutex; use tauri::AppHandle; -use tauri::{TitleBarStyle, WebviewUrl, WebviewWindowBuilder}; - +use tauri::Emitter; +use tauri::{WebviewUrl, WebviewWindowBuilder}; struct WatcherState { watcher: Option, @@ -25,8 +24,7 @@ fn process_png_file(path: &PathBuf, app: AppHandle) -> Result<(), String> { println!("Processing PNG file: {}", path.display()); // Read the file - let contents = fs::read(path) - .map_err(|e| format!("Failed to read file: {}", e))?; + let contents = fs::read(path).map_err(|e| format!("Failed to read file: {}", e))?; // Convert to base64 let base64_string = BASE64.encode(&contents); @@ -47,26 +45,27 @@ async fn handle_selected_folder( app: AppHandle, ) -> Result { let path_buf = PathBuf::from(&path); - + if !path_buf.exists() || !path_buf.is_dir() { return Err("Invalid directory path".to_string()); } // Stop existing watcher if any - let mut state = state.lock().map_err(|_| "Failed to lock state".to_string())?; + let mut state = state + .lock() + .map_err(|_| "Failed to lock state".to_string())?; state.watcher = None; // Create a channel to receive file system events let (tx, rx) = channel(); // Create a new watcher - let mut watcher = RecommendedWatcher::new( - tx, - Config::default(), - ).map_err(|e| format!("Failed to create watcher: {}", e))?; + let mut watcher = RecommendedWatcher::new(tx, Config::default()) + .map_err(|e| format!("Failed to create watcher: {}", e))?; // Start watching the directory - watcher.watch(path_buf.as_ref(), RecursiveMode::Recursive) + watcher + .watch(path_buf.as_ref(), RecursiveMode::Recursive) .map_err(|e| format!("Failed to watch directory: {}", e))?; // Store the watcher in state @@ -114,38 +113,36 @@ pub fn run() { .manage(watcher_state) .invoke_handler(tauri::generate_handler![handle_selected_folder]) .setup(|app| { - let win_builder = - WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) - .hidden_title(true) + let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) .inner_size(480.0, 360.0) .resizable(false); // set transparent title bar only when building for macOS #[cfg(target_os = "macos")] let win_builder = win_builder.title_bar_style(TitleBarStyle::Transparent); - + let window = win_builder.build().unwrap(); - + // set background color only when building for macOS #[cfg(target_os = "macos")] { - use cocoa::appkit::{NSColor, NSWindow}; - use cocoa::base::{id, nil}; - - let ns_window = window.ns_window().unwrap() as id; - unsafe { - let bg_color = NSColor::colorWithRed_green_blue_alpha_( - nil, - 245.0 / 255.0, - 245.0 / 255.0, - 245.0 / 255.0, - 1.0, - ); - ns_window.setBackgroundColor_(bg_color); - } + use cocoa::appkit::{NSColor, NSWindow}; + use cocoa::base::{id, nil}; + + let ns_window = window.ns_window().unwrap() as id; + unsafe { + let bg_color = NSColor::colorWithRed_green_blue_alpha_( + nil, + 245.0 / 255.0, + 245.0 / 255.0, + 245.0 / 255.0, + 1.0, + ); + ns_window.setBackgroundColor_(bg_color); + } } - + Ok(()) - }) + }) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index 2aaa7b5..d056e73 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -1,30 +1,30 @@ { - "$schema": "https://schema.tauri.app/config/2", - "productName": "haystack", - "version": "0.1.0", - "identifier": "com.haystack.app", - "build": { - "beforeDevCommand": "bun run dev", - "devUrl": "http://localhost:1420", - "beforeBuildCommand": "bun run build", - "frontendDist": "../dist" - }, - "app": { - "windows": [], - "macOSPrivateApi": true, - "security": { - "csp": null - } - }, - "bundle": { - "active": true, - "targets": "all", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ] - } + "$schema": "https://schema.tauri.app/config/2", + "productName": "haystack", + "version": "0.1.0", + "identifier": "com.haystack.app", + "build": { + "beforeDevCommand": "bun run dev", + "devUrl": "http://localhost:1420", + "beforeBuildCommand": "bun run build", + "frontendDist": "../dist" + }, + "app": { + "windows": [], + "macOSPrivateApi": true, + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] + } } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2129247..cd87c9e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,105 +4,105 @@ import { IconSearch, IconRefresh } from "@tabler/icons-solidjs"; import clsx from "clsx"; type Emoji = { - emoji: string; - name: string; + emoji: string; + name: string; }; function App() { - const [options, setOptions] = createSignal([]); - const [emoji, setEmoji] = createSignal(null); + const [options, setOptions] = createSignal([]); + const [emoji, setEmoji] = createSignal(null); - const emojiData: Emoji[] = [ - { emoji: "😀", name: "Grinning Face" }, - { emoji: "😃", name: "Grinning Face with Big Eyes" }, - { emoji: "😄", name: "Grinning Face with Smiling Eyes" }, - { emoji: "😁", name: "Beaming Face with Smiling Eyes" }, - { emoji: "😆", name: "Grinning Squinting Face" }, - ]; + const emojiData: Emoji[] = [ + { emoji: "😀", name: "Grinning Face" }, + { emoji: "😃", name: "Grinning Face with Big Eyes" }, + { emoji: "😄", name: "Grinning Face with Smiling Eyes" }, + { emoji: "😁", name: "Beaming Face with Smiling Eyes" }, + { emoji: "😆", name: "Grinning Squinting Face" }, + ]; - const queryEmojiData = (query: string) => { - return emojiData.filter((emoji) => - emoji.name.toLowerCase().includes(query.toLowerCase()) - ); - }; + const queryEmojiData = (query: string) => { + return emojiData.filter((emoji) => + emoji.name.toLowerCase().includes(query.toLowerCase()), + ); + }; - return ( -
-
- setOptions(queryEmojiData(query))} - onChange={(result) => setEmoji(result)} - optionValue="name" - optionLabel="name" - placeholder="Search for stuff..." - itemComponent={(props) => ( - - - {props.item.rawValue.emoji} - - - )} - > - - - - - } - > - - - - - - - - e.preventDefault()} - > - - - 😬 No emoji found - - - - -
- {/*
+ return ( +
+
+ setOptions(queryEmojiData(query))} + onChange={(result) => setEmoji(result)} + optionValue="name" + optionLabel="name" + placeholder="Search for stuff..." + itemComponent={(props) => ( + + + {props.item.rawValue.emoji} + + + )} + > + + + + + } + > + + + + + + + + e.preventDefault()} + > + + + 😬 No emoji found + + + + +
+ {/*
Emoji selected: {emoji()?.emoji} {emoji()?.name}
*/} -
-
-
-
-
-
-
-
-
-
-
-
-
-
- footer -
-
- ); +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ footer +
+
+ ); } export default App; diff --git a/frontend/src/components/FolderPicker.tsx b/frontend/src/components/FolderPicker.tsx index 585fbbe..285a2bb 100644 --- a/frontend/src/components/FolderPicker.tsx +++ b/frontend/src/components/FolderPicker.tsx @@ -3,47 +3,47 @@ import { open } from "@tauri-apps/plugin-dialog"; import { invoke } from "@tauri-apps/api/core"; export function FolderPicker() { - const [selectedPath, setSelectedPath] = createSignal(""); - const [status, setStatus] = createSignal(""); + const [selectedPath, setSelectedPath] = createSignal(""); + const [status, setStatus] = createSignal(""); - const handleFolderSelect = async () => { - try { - const selected = await open({ - directory: true, - multiple: false, - }); + const handleFolderSelect = async () => { + try { + const selected = await open({ + directory: true, + multiple: false, + }); - if (selected) { - setSelectedPath(selected as string); - // Send the path to Rust - const response = await invoke("handle_selected_folder", { - path: selected, - }); - setStatus(`Folder processed: ${response}`); - } - } catch (error) { - setStatus(`Error: ${error}`); - } - }; + if (selected) { + setSelectedPath(selected as string); + // Send the path to Rust + const response = await invoke("handle_selected_folder", { + path: selected, + }); + setStatus(`Folder processed: ${response}`); + } + } catch (error) { + setStatus(`Error: ${error}`); + } + }; - return ( -
- + return ( +
+ - {selectedPath() && ( -
-

Selected folder:

-

{selectedPath()}

-
- )} + {selectedPath() && ( +
+

Selected folder:

+

{selectedPath()}

+
+ )} - {status() &&

{status()}

} -
- ); + {status() &&

{status()}

} +
+ ); } diff --git a/frontend/src/components/ImageViewer.tsx b/frontend/src/components/ImageViewer.tsx index 85fc08a..2fffb5c 100644 --- a/frontend/src/components/ImageViewer.tsx +++ b/frontend/src/components/ImageViewer.tsx @@ -3,35 +3,35 @@ import { listen } from "@tauri-apps/api/event"; import { FolderPicker } from "./FolderPicker"; export function ImageViewer() { - const [latestImage, setLatestImage] = createSignal(null); + const [latestImage, setLatestImage] = createSignal(null); - createEffect(() => { - // Listen for PNG processing events - const unlisten = listen("png-processed", (event) => { - console.log("Received processed PNG"); - const base64Data = event.payload as string; - setLatestImage(`data:image/png;base64,${base64Data}`); - }); + createEffect(() => { + // Listen for PNG processing events + const unlisten = listen("png-processed", (event) => { + console.log("Received processed PNG"); + const base64Data = event.payload as string; + setLatestImage(`data:image/png;base64,${base64Data}`); + }); - return () => { - unlisten.then((fn) => fn()); // Cleanup listener - }; - }); + return () => { + unlisten.then((fn) => fn()); // Cleanup listener + }; + }); - return ( -
- + return ( +
+ - {latestImage() && ( -
-

Latest Processed Image:

- Latest processed -
- )} -
- ); + {latestImage() && ( +
+

Latest Processed Image:

+ Latest processed +
+ )} +
+ ); } diff --git a/frontend/src/index.css b/frontend/src/index.css index 71bc21a..d61995c 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -3,21 +3,21 @@ @tailwind utilities; @font-face { - font-family: "Manrope"; - src: url("./assets/fonts/Manrope-VariableFont_wght.ttf") format("truetype"); - font-weight: 100 900; - font-display: swap; + font-family: "Manrope"; + src: url("./assets/fonts/Manrope-VariableFont_wght.ttf") format("truetype"); + font-weight: 100 900; + font-display: swap; } :root { - @apply bg-neutral-100 text-black rounded-xl; - font-family: Manrope, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 500; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; + @apply bg-neutral-100 text-black rounded-xl; + font-family: Manrope, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 500; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; } diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 97f179f..f749829 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,15 +1,15 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], - theme: { - extend: { - fontFamily: { - sans: ["Manrope", "sans-serif"], - }, - }, - }, - plugins: [ - require("@kobalte/tailwindcss"), - require("tailwind-scrollbar-hide"), - ], + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: { + fontFamily: { + sans: ["Manrope", "sans-serif"], + }, + }, + }, + plugins: [ + require("@kobalte/tailwindcss"), + require("tailwind-scrollbar-hide"), + ], }; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 3999958..f7f13c7 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,26 +1,26 @@ { - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "jsxImportSource": "solid-js", + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json index 42872c5..eca6668 100644 --- a/frontend/tsconfig.node.json +++ b/frontend/tsconfig.node.json @@ -1,10 +1,10 @@ { - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] } diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index af994b4..815ec0f 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -8,31 +8,31 @@ const host = process.env.TAURI_DEV_HOST; // https://vitejs.dev/config/ export default defineConfig(async () => ({ - plugins: [solid()], - css: { - postcss: { - plugins: [tailwindcss, autoprefixer], - }, - }, - // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` - // - // 1. prevent vite from obscuring rust errors - clearScreen: false, - // 2. tauri expects a fixed port, fail if that port is not available - server: { - port: 1420, - strictPort: true, - host: host || false, - hmr: host - ? { - protocol: "ws", - host, - port: 1421, - } - : undefined, - watch: { - // 3. tell vite to ignore watching `src-tauri` - ignored: ["**/src-tauri/**"], - }, - }, + plugins: [solid()], + css: { + postcss: { + plugins: [tailwindcss, autoprefixer], + }, + }, + // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` + // + // 1. prevent vite from obscuring rust errors + clearScreen: false, + // 2. tauri expects a fixed port, fail if that port is not available + server: { + port: 1420, + strictPort: true, + host: host || false, + hmr: host + ? { + protocol: "ws", + host, + port: 1421, + } + : undefined, + watch: { + // 3. tell vite to ignore watching `src-tauri` + ignored: ["**/src-tauri/**"], + }, + }, }));