diff --git a/.gitignore b/.gitignore index 13f6b3d..b620170 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ target/ src-tauri/target/ src-tauri/gen/ window-state.json +*.tar.gz +*.tar.xz diff --git a/AUDIT_LOG.md b/AUDIT_LOG.md index d4d6c04..db40a18 100644 --- a/AUDIT_LOG.md +++ b/AUDIT_LOG.md @@ -2,6 +2,52 @@ This log tracks all significant changes, updates, and versions in the PaperCache project. +## 2026-06-24 - (Uncommitted) +**Change:** feat: graph view rebuilt, Windows focus-loss fix, Cmd+/ shortcuts, welcome revamp (v0.5.3) + +**Details/Why:** +Major graph view overhaul and cross-platform fixes: + +1. **Flat Circle Nodes with Occlusion**: Replaced default 3D spheres with `CircleGeometry` meshes. Circles render in the transparent pass at `renderOrder: 1` (after edges), with `depthWrite: true` — edges passing through nodes are now cleanly occluded. + +2. **Always-Visible Labels**: Each node returns a `THREE.Group` containing the circle mesh plus a canvas-based `THREE.Sprite` label. Labels are positioned below each circle and always visible (never fade on zoom). + +3. **Cmd+F Fuzzy Search in Graph**: Search bar with character-order fuzzy matching, arrow-key navigation, and Enter to fly the camera to the matched node. + +4. **Folder Clustering**: `d3-force` `forceX`/`forceY` at 0.008 strength weakly attract same-folder nodes toward shared centroids on a 60-unit radius, creating subtle visual groupings. + +5. **Cmd+Shift+N No Longer Hides Open App**: Changed the Rust global shortcut handler in `shortcuts.rs` — for `new-note` action, window only shows if hidden; never hides when already visible. All other shortcuts (toggle, etc.) retain `toggle_window` behavior. + +6. **Windows Focus-Loss Debounce**: `lib.rs` focus-loss handler now uses a 200ms debounce via `AtomicBool` + `std::thread::spawn`. Clicking the title bar on Windows 10 briefly triggers `Focused(false)` — the debounce waits 200ms for a matching `Focused(true)` before hiding. On macOS, hide remains immediate. + +7. **Cmd+/ Shortcuts Reference**: New shortcut opens or auto-creates `Shortcuts.md` with all keyboard shortcuts and slash commands listed. + +8. **Fresh Install Welcome**: Version check in `App.tsx` detects `null` last-seen-version (fresh install) and opens `Welcome.md` instead of looking for a new-features note. The Rust onboarding template (`fs.rs`) was revamped with a bullet-list feature overview. + +9. **Lazy-Loaded Graph**: `GraphView` dynamically imported via `React.lazy()` — Three.js bundle (~1.3 MB) loads only on first graph open. + +10. **Doc Updates**: Version bumped to 0.5.3 across all manifest files. `CHANGELOG.md`, `features.md`, `README.md`, `notes/New Features in v0.5.3.md` all updated. + +--- + +## 2026-06-24 - Native Notifications, Timers, DSL Engine, WebGL Graph +**Change:** feat: native notifications, timers, DSL regex engine, WebGL graph with folder attraction + +**Details/Why:** +Implemented four major platform features as requested: + +1. **Native Reminder Notifications (Rust Backend):** Removed the old Web Notification API + `setTimeout` polling loop from the JS renderer. All reminder scheduling is now delegated to a new `commands/notifications.rs` Rust module. Uses `tokio::spawn` + `tokio::time::sleep` to wait for exact due times and fires native OS notifications via `tauri_plugin_notification`. This ensures reminders are reliable when the app is minimized, handles OS notification permission gracefully, and eliminates renderer-side timer drift. A `reminder-fired` Tauri event is emitted to the frontend to show an in-app toast and update localStorage. + +2. **Timers:** Added a new `useTimerStore.ts` Zustand store and `TimersPage.tsx` component with a glassmorphic panel UI. Countdowns use a chained `setTimeout` pattern (no `setInterval`) for drift-corrected display. The Rust backend (`schedule_timer` / `cancel_timer` commands) fires the native OS notification and emits `timer-complete` on completion — ensuring timers complete even when minimized. A "Timers" button was added to `MainActionMenu`, and the `/timer` slash command was added to the editor. + +3. **DSL Regex Parsing Engine:** Created `src/lib/editor/dslPlugin.ts` — a factory `createRegexPlugin(rules: DSLRule[])` that generates CodeMirror ViewPlugins. Scans only `view.visibleRanges` per update tick (O(visible lines)), guaranteeing lag-free typing at any document size. Supports `className` mark decorations, `widget` factories, and `onMatch` callbacks per rule. + +4. **WebGL Graph with Folder Attraction:** Replaced `react-force-graph-2d` (Canvas 2D) with `react-force-graph-3d` (Three.js / WebGL) lazy-loaded via `React.Suspense`. The graph is configured in 2D mode (z-axis locked). Added custom `d3-force` `forceX` and `forceY` forces that pull nodes toward per-folder centroid positions, creating organic cluster layouts where notes from the same folder attract each other. + +**Files changed:** `src-tauri/src/commands/notifications.rs` [NEW], `src-tauri/src/commands/mod.rs`, `src-tauri/src/lib.rs`, `src-tauri/Cargo.toml`, `src-tauri/capabilities/default.json`, `package.json`, `src/types.d.ts`, `src/api.ts`, `src/hooks/useReminders.ts`, `src/hooks/useReminders.test.ts`, `src/store/useAppStore.ts`, `src/store/useTimerStore.ts` [NEW], `src/components/TimersPage.tsx` [NEW], `src/components/MainActionMenu.tsx`, `src/lib/editor/slashCommands.ts`, `src/lib/editor/dslPlugin.ts` [NEW], `src/GraphView.tsx`, `src/App.tsx`, `src/App.css`. + +--- + ## 2026-06-24 - (Uncommitted) **Change:** feat: add slash command autosuggest, auto-open new features note, and tag action menu for v0.5.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index e75fa1a..76a2e2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,36 @@ All notable, user-facing changes to PaperCache will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v0.5.3] - 2026-06-24 + +### Added +- **Redesigned Graph View**: Nodes are now flat `CircleGeometry` with `depthWrite: true` and `renderOrder: 1` in the transparent pass, cleanly occluding edges behind them. Always-visible canvas-based text labels positioned below each node. +- **Cmd+F Fuzzy Search in Graph**: Press `Cmd+F` in graph view to search note names by fuzzy character matching. Navigate with arrow keys, confirm with Enter to fly the camera to the matching node. +- **Folder Clustering**: Notes sharing a folder are weakly attracted to a shared centroid via forceX/forceY at 0.008 strength, producing subtle visual grouping without breaking the unified cluster. +- **Cmd+/ Shortcuts Reference**: Press `Cmd+/` (or `Cmd+?`) to open or create a `Shortcuts.md` note listing all keyboard shortcuts and slash commands. +- **Fresh Install Welcome**: First-time launch now opens `Welcome.md` instead of looking for a new-features note. The welcome note has been revamped with a full feature overview. +- **Lazy-Loaded Graph**: `GraphView` is dynamically imported with `React.lazy()` so the Three.js bundle (~1.3 MB) loads only when the graph is opened. +- **Smooth Graph Fade-in**: The graph overlay animates in with a 250ms CSS keyframe fade. +- **Persistent Node Positions**: After closing the graph view, node positions are cached and restored on next open, preserving manual arrangement. +- **Native OS Reminder Notifications**: Task reminders (`/task`) now fire native OS notifications via the Rust backend using `tokio::time::sleep` + `tauri_plugin_notification`. Notifications fire reliably even when the app is minimized or out of focus, and gracefully handle OS-level permission denials. +- **Countdown Timers**: New timer panel (accessible via the action menu or `/timer` command) lets you create, view, pause/resume, and cancel countdown timers. Timers display a live countdown using drift-corrected `setTimeout` chains and trigger both a native OS notification and an in-app alert on completion — even if you're viewing a different note. +- **DSL Regex Parsing Engine**: New `createRegexPlugin()` factory in `dslPlugin.ts` enables flexible, regex-based Domain Specific Language parsing in the editor. Scans only visible ranges for O(visible lines) performance — lag-free at any document size. Supports custom mark decorations, widget injections, and match callbacks. +- **WebGL Graph View**: The Graph View has been rewritten using Three.js WebGL via `react-force-graph-3d`. Notes in the same folder are attracted to shared centroid positions via custom `d3-force` simulation rules, causing them to cluster together naturally. The graph is lazy-loaded to avoid impacting editor startup time. + +### Changed +- **Cmd+Shift+N Behavior**: The global new-note shortcut no longer hides the app if it's already visible. It only shows the window when hidden. The shortcut always creates a new note regardless. +- **Node Circle Size**: Increased from radius 8 to 12, with labels shifted and scaled accordingly. +- **Windows Focus-Loss Debounce**: Hiding on focus loss now uses a 200ms debounce to prevent accidental hide when clicking the title bar for drag or resize. +- **Node Positions Cache**: Force simulation no longer pushes dragged nodes back — the strength accessor skips nodes in the dragged set. +- **Graph Controls**: OrbitControls configured with `enableRotate = false`, `LEFT = PAN`, `MIDDLE = DOLLY` for a pure 2D navigation experience. + +### Fixed +- Fixed edges/lines showing through circle nodes by making circle meshes render in the transparent pass after links. +- Fixed graph view opening inside the shortcut handler (removed stale `showGraphView` setter call from version check effect). +- Fixed blank graph issue on re-open by caching node positions at component unmount. + +--- + ## [v0.5.2] - 2026-06-24 ### Added diff --git a/README.md b/README.md index 28782d6..da417cd 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Summon it with a hotkey. Jot. Dismiss. It stays out of your way until you need i - **Interactive Checkboxes & Slash Commands** — Type `/` to see inline autosuggestions (like `/check`, `/task`, or `/ai`). Press `Tab` to instantly complete them. Checkboxes strike through text when clicked. - **Tasks & Reminders** — Type `/task` followed by `@ 1d2h` to set a due date. Press `Cmd+T` to open a unified Tasks view that tracks all your pending items and due times. - **Tags & folders** — `!tagname` for tags, `/` in note titles for folders. Right-click any tag pill to export or delete all tagged notes at once. -- **Graph view** — see how your notes connect (`Cmd+G`). +- **Graph view** — press `Cmd+G` to open a 2D knowledge graph with flat circle nodes, always-visible labels, and folder-based clustering. Press `Cmd+F` to fuzzy-search nodes and fly directly to the match. > **Deep Dive:** For a comprehensive list of every single feature in PaperCache, check out [features.md](features.md). > **Performance:** We take speed and battery life seriously. Check out our [Performance Audit](PERFORMANCE_AUDIT.md). @@ -81,14 +81,16 @@ Built with Tauri, Rust, React, TypeScript, and Vite. | `Cmd+Shift+N` | New note (global, configurable) | | `Cmd+Shift+S` | Open settings panel | | `Cmd+N` | New note (in-app) | +| `Cmd+/` | Open shortcuts reference | | `Cmd+T` | Open Tasks page | | `Cmd+K` | Main action menu | | `Cmd+P` | Search notes | | `Cmd+G` | Graph view | +| `Cmd+F` | Search in graph (while graph is open) | | `Cmd+H` | Highlight selected text | | `Cmd+E` | Export note | | `Cmd+Click` | Follow internal link | -| `Esc` | Close menus or modals | +| `Esc` | Close menus / modals | --- diff --git a/features.md b/features.md index 46d8fdc..1274c27 100644 --- a/features.md +++ b/features.md @@ -25,10 +25,16 @@ This document outlines every feature available in the PaperCache codebase, organ - **Note Folders**: Implicitly organize notes into folders by adding a `/` in the title (e.g., `projects/PaperCache.md`). Folders are auto-detected, color-coded, and cleanly removed from disk if they become empty. - **Internal Note Linking**: Link to other notes using markdown links like `[link text](/file Note.md)` or simply `/file Note.md`. Click the link with `Cmd+Click` or `Ctrl+Click` to instantly navigate to it. URL links also open in the system browser. -- **Interactive Graph View**: An interactive, visual 2D node graph (`Cmd+G`) showing all connected notes, color-coded automatically based on their implicit folder. Click a node to open it. +- **Interactive Graph View** (`Cmd+G`): An interactive 2D knowledge graph rendered with Three.js WebGL. Nodes are clean flat circles with always-visible labels, edges are colored by opacity. Features: + - **Folder Clustering**: Notes in the same folder are gently attracted toward a shared centroid, creating subtle visual groupings. + - **Cmd+F Fuzzy Search**: Press `Cmd+F` inside graph view to fuzzy-search note names. Navigate with arrow keys, press Enter to fly the camera directly to the matched node. + - **Drag to Rearrange**: Nodes can be dragged freely; positions are cached and restored across graph sessions. + - **Smooth Fade-in**: The graph overlay animates in with a 250ms fade. + - **Lazy-Loaded**: The Three.js bundle (~1.3 MB) loads only when the graph is first opened, keeping startup fast. - **Global Note Search**: Open an omnibar search (`Cmd+P`) to quickly fuzzy-search note contents and file names across the entire workspace. - **Tagging System & Context Menu**: Add inline tags using `!tagname`. The global search bar aggregates all unique tags as clickable filters to quickly isolate notes. Right-click any tag pill to open an inline action menu, allowing you to bulk-delete or export all notes containing that tag into a single Markdown file. - **Auto-Renaming**: Notes are auto-created with a timestamp ID. The title is intelligently inferred from the first line of the file (e.g., `# Header`), but can also be manually renamed by clicking the title bar. +- **Shortcuts Reference** (`Cmd+/` or `Cmd+?`): Press this anywhere in the app to open or create a `Shortcuts.md` note listing every keyboard shortcut and slash command. ## Artificial Intelligence @@ -40,11 +46,11 @@ This document outlines every feature available in the PaperCache codebase, organ ## Desktop System Integration -- **Stealth / Background Mode**: Click away or lose focus, and the app instantly hides itself. On macOS, it runs as an "accessory" and hides its dock icon completely, acting like a true floating utility. +- **Stealth / Background Mode**: Click away or lose focus, and the app instantly hides itself (macOS) or after a brief debounce (Windows/Linux — prevents accidental hide when dragging the title bar). On macOS, it runs as an "accessory" and hides its dock icon completely, acting like a true floating utility. - **Intelligent Multi-Monitor Support**: When summoning the app via its global hotkey, it detects the active screen your mouse is currently on and brings the window instantly to that specific screen's workspace. - **System Tray Icon**: A minimal system tray icon for toggling visibility or quitting the app cleanly, adapting to the user's OS theme (light/dark). - **Global Hotkeys**: - - `Cmd+Shift+N` (configurable): Instantly spawn a new floating note from anywhere on your OS. + - `Cmd+Shift+N` (configurable): Spawn a new note from anywhere. If the app is already open, creates the note without hiding. - `Cmd+Shift+C` (configurable): Toggle PaperCache visibility from anywhere on your OS. - **State Memory**: Memorizes precise window coordinates, dimensions, and zoom levels across launches to persist workspace state. - **Fluid Settings**: Opening the Settings menu dynamically inherits the exact dimensions and on-screen coordinates of your current notepad for a native, seamless transition. @@ -52,3 +58,5 @@ This document outlines every feature available in the PaperCache codebase, organ - **Exporting Options**: Export individual notes straight to a local `.md` file on your filesystem via the main menu or search list. - **Safe Tutorials**: Auto-generates fully functional Markdown tutorials in a `commands/` folder upon first launch. Prevents accidental deletion of these core tutorial files. - **Smart Version Updates**: Upon updating to a new release, PaperCache automatically opens a "New Features" summary note on your first launch and cleanly deletes older version notes behind the scenes to keep your workspace tidy. +- **Fresh Install Welcome**: First-time users automatically open to a revamped `Welcome.md` note with a complete feature overview instead of an empty editor. +- **Node Positions Persist**: After closing the graph view, node positions are cached and restored on next open, preserving manual arrangement. diff --git a/notes/New Features in v0.5.3.md b/notes/New Features in v0.5.3.md new file mode 100644 index 0000000..e40d60a --- /dev/null +++ b/notes/New Features in v0.5.3.md @@ -0,0 +1,16 @@ +# New Features in v0.5.3 + +Welcome to PaperCache v0.5.3! + +Here are the new features implemented in this version: +- **Redesigned Graph View**: Nodes are now rendered as clean, flat circles that properly occlude edges passing through them. Labels are always visible below each node. Circle size increased for better readability. +- **Cmd+F Fuzzy Search in Graph**: Press `Cmd+F` in graph view to fuzzy-search note names. Navigate results with arrow keys, press Enter to pan/zoom to the matched node. +- **Folder Clustering**: Notes in the same folder are gently attracted toward a shared centroid, creating subtle visual groupings. The graph still forms a single connected cluster. +- **Better Cmd+Shift+N Behavior**: When the app is already open, the global new-note shortcut now creates a new note without hiding the window. It only toggles visibility when the app is hidden. +- **Windows Focus-Loss Fix**: Clicking the title bar to drag or resize on Windows no longer accidentally hides the app. +- **Fresh Install Welcome**: First-time users now automatically open to the `Welcome.md` note with a feature overview. +- **Shortcuts Reference**: Press `Cmd+/` to open a `Shortcuts.md` note listing all keyboard shortcuts and slash commands. +- **Fade-in Animation**: The graph view now fades in smoothly when opened. +- **Lazy-Loaded Graph**: The Three.js graph engine is lazy-loaded, keeping the main bundle lean and startup fast. + +*(If you have read this note, feel free to delete it)* diff --git a/package-lock.json b/package-lock.json index 5aaa462..5933482 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,27 @@ { "name": "papercache", - "version": "0.5.2", + "version": "0.5.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "papercache", - "version": "0.5.2", + "version": "0.5.3", "dependencies": { "@tauri-apps/api": "^2.11.1", "@tauri-apps/plugin-autostart": "^2.5.1", "@tauri-apps/plugin-dialog": "^2.7.1", "@tauri-apps/plugin-fs": "^2.5.1", "@tauri-apps/plugin-global-shortcut": "^2.3.2", + "@tauri-apps/plugin-notification": "^2.3.3", "@tauri-apps/plugin-shell": "^2.3.5", "@tauri-apps/plugin-updater": "^2.10.1", "@tauri-apps/plugin-window-state": "^2.4.1", - "expr-eval": "^2.0.2" + "@types/d3-force": "^3.0.10", + "d3-force": "^3.0.0", + "expr-eval": "^2.0.2", + "react-force-graph-3d": "^1.29.1", + "three": "^0.184.0" }, "devDependencies": { "@codemirror/commands": "^6.10.3", @@ -50,12 +55,15 @@ "prettier": "^3.8.3", "react": "^19.2.6", "react-dom": "^19.2.6", - "react-force-graph-2d": "^1.29.1", "typescript": "~6.0.2", "typescript-eslint": "^8.59.2", "vite": "^8.0.12", "vitest": "^4.1.7", "zustand": "^5.0.14" + }, + "optionalDependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1" } }, "node_modules/@adobe/css-tools": { @@ -313,7 +321,6 @@ "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -394,6 +401,7 @@ "version": "6.20.3", "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", + "dev": true, "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -483,6 +491,7 @@ "version": "6.12.3", "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "dev": true, "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", @@ -521,6 +530,7 @@ "version": "6.7.0", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.7.0.tgz", "integrity": "sha512-Zbl9NyscLMZkfXPQnNAIIAFftidrA1UbcJEIMp24C0Bukc2I5T8wJS0wsXYsnDOqCFJUeJ1BITGNs5CqPDSmSg==", + "dev": true, "license": "MIT", "dependencies": { "@marijn/find-cluster-break": "^1.0.0" @@ -543,6 +553,7 @@ "version": "6.43.2", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.2.tgz", "integrity": "sha512-8kU6WNRYBKV9Sw3cxNz+uSvUvx3tt+1qgupGFPubnbLFDHOgh5qQdIGmXcD7bkA/PROK6LDKVhKMpcY7H++Amg==", + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -723,7 +734,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1438,6 +1448,7 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "dev": true, "license": "MIT" }, "node_modules/@lezer/css": { @@ -1456,6 +1467,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "dev": true, "license": "MIT", "dependencies": { "@lezer/common": "^1.3.0" @@ -1489,6 +1501,7 @@ "version": "1.4.10", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "dev": true, "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" @@ -1509,6 +1522,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "dev": true, "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { @@ -2087,6 +2101,15 @@ "@tauri-apps/api": "^2.11.0" } }, + "node_modules/@tauri-apps/plugin-notification": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.3.3.tgz", + "integrity": "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.8.0" + } + }, "node_modules/@tauri-apps/plugin-shell": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.3.5.tgz", @@ -2194,7 +2217,6 @@ "version": "25.0.0", "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", - "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { @@ -2226,6 +2248,12 @@ "assertion-error": "^2.0.1" } }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -2757,11 +2785,26 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/3d-force-graph": { + "version": "1.80.0", + "resolved": "https://registry.npmjs.org/3d-force-graph/-/3d-force-graph-1.80.0.tgz", + "integrity": "sha512-tzI353gW1nXPpnC7VTa3JjMg+3cp77qOLUFO0vucPTfF+q5R6sQsNsIqVTbRIb7RSypn14nBa4yfkOe9ThxASw==", + "license": "MIT", + "dependencies": { + "accessor-fn": "1", + "kapsule": "^1.16", + "three": ">=0.179 <1", + "three-forcegraph": "1", + "three-render-objects": "^1.41" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/accessor-fn": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -2909,17 +2952,6 @@ "node": ">=6.0.0" } }, - "node_modules/bezier-js": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", - "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" - } - }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -2999,19 +3031,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas-color-tracker": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", - "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinycolor2": "^1.6.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -3082,6 +3101,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -3131,7 +3151,6 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "dev": true, "license": "ISC", "dependencies": { "internmap": "1 - 2" @@ -3144,14 +3163,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", - "dev": true, "license": "MIT" }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -3161,41 +3178,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/d3-drag": { + "node_modules/d3-force": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "dev": true, + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", - "d3-selection": "3" + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" }, "engines": { "node": ">=12" } }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, "node_modules/d3-force-3d": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", - "dev": true, "license": "MIT", "dependencies": { "d3-binarytree": "1", @@ -3212,7 +3217,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -3222,7 +3226,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "dev": true, "license": "ISC", "dependencies": { "d3-color": "1 - 3" @@ -3235,14 +3238,12 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", - "dev": true, "license": "MIT" }, "node_modules/d3-quadtree": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -3252,7 +3253,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "dev": true, "license": "ISC", "dependencies": { "d3-array": "2.10.0 - 3", @@ -3269,7 +3269,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "dev": true, "license": "ISC", "dependencies": { "d3-color": "1 - 3", @@ -3283,9 +3282,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "dev": true, "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -3294,7 +3291,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "dev": true, "license": "ISC", "dependencies": { "d3-array": "2 - 3" @@ -3307,7 +3303,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "dev": true, "license": "ISC", "dependencies": { "d3-time": "1 - 3" @@ -3320,44 +3315,18 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "dev": true, - "license": "ISC", + "node_modules/data-bind-mapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/data-bind-mapper/-/data-bind-mapper-1.0.3.tgz", + "integrity": "sha512-QmU3lyEnbENQPo0M1F9BMu4s6cqNNp8iJA+b/HP2sSb7pf3dxwF3+EP1eO69rwBfH9kFJ1apmzrtogAmVt2/Xw==", + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" + "accessor-fn": "1" }, "engines": { "node": ">=12" @@ -3917,7 +3886,6 @@ "version": "1.7.5", "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", - "dev": true, "license": "MIT", "dependencies": { "d3-selection": "2 - 3", @@ -3928,33 +3896,6 @@ "node": ">=12" } }, - "node_modules/force-graph": { - "version": "1.51.4", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.4.tgz", - "integrity": "sha512-TdJ2KbkoiDQ7NIRx8IPGD0mAXXpLhamS7c+b7W98b0MHG7lphnda1VOQX/98UDTsttIAdH4TcP0l0MauSnLK8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "bezier-js": "3 - 6", - "canvas-color-tracker": "^1.3", - "d3-array": "1 - 3", - "d3-drag": "2 - 3", - "d3-force-3d": "2 - 3", - "d3-scale": "1 - 4", - "d3-scale-chromatic": "1 - 3", - "d3-selection": "2 - 3", - "d3-zoom": "2 - 3", - "float-tooltip": "^1.7", - "index-array-by": "1", - "kapsule": "^1.16", - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4112,21 +4053,10 @@ "node": ">=8" } }, - "node_modules/index-array-by": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", - "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/internmap": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4228,7 +4158,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.2.tgz", "integrity": "sha512-YKnxXEekXKzhpf7CLYA0A+oDP8V0OhICNCr5lv96FvSsDEmrb0GKM776JgQvHTMjr7DTTPEVv/1Ciaw0uEWzBA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4238,7 +4167,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/jsdom": { @@ -4343,7 +4271,6 @@ "version": "1.16.3", "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", - "dev": true, "license": "MIT", "dependencies": { "lodash-es": "4" @@ -4699,7 +4626,6 @@ "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", - "dev": true, "license": "MIT" }, "node_modules/log-update": { @@ -4792,7 +4718,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4951,6 +4876,44 @@ "dev": true, "license": "MIT" }, + "node_modules/ngraph.events": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.4.0.tgz", + "integrity": "sha512-NeDGI4DSyjBNBRtA86222JoYietsmCXbs8CEB0dZ51Xeh4lhVl1y3wpWLumczvnha8sFQIW4E0vvVWwgmX2mGw==", + "license": "BSD-3-Clause" + }, + "node_modules/ngraph.forcelayout": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-3.3.1.tgz", + "integrity": "sha512-MKBuEh1wujyQHFTW57y5vd/uuEOK0XfXYxm3lC7kktjJLRdt/KEKEknyOlc6tjXflqBKEuYBBcu7Ax5VY+S6aw==", + "license": "BSD-3-Clause", + "dependencies": { + "ngraph.events": "^1.0.0", + "ngraph.merge": "^1.0.0", + "ngraph.random": "^1.0.0" + } + }, + "node_modules/ngraph.graph": { + "version": "20.1.2", + "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-20.1.2.tgz", + "integrity": "sha512-W/G3GBR3Y5UxMLHTUCPP9v+pbtpzwuAEIqP5oZV+9IwgxAIEZwh+Foc60iPc1idlnK7Zxu0p3puxAyNmDvBd0Q==", + "license": "BSD-3-Clause", + "dependencies": { + "ngraph.events": "^1.4.0" + } + }, + "node_modules/ngraph.merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-1.0.0.tgz", + "integrity": "sha512-5J8YjGITUJeapsomtTALYsw7rFveYkM+lBj3QiYZ79EymQcuri65Nw3knQtFxQBU1r5iOaVRXrSwMENUPK62Vg==", + "license": "MIT" + }, + "node_modules/ngraph.random": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-1.2.0.tgz", + "integrity": "sha512-4EUeAGbB2HWX9njd6bP6tciN6ByJfoaAvmVL9QTaZSeXrW46eNGA9GajiXiPBbvFqxUWFkEbyo6x5qsACUuVfA==", + "license": "BSD-3-Clause" + }, "node_modules/node-releases": { "version": "2.0.49", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.49.tgz", @@ -4965,7 +4928,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5111,6 +5073,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/postcss": { "version": "8.5.15", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", @@ -5144,7 +5118,6 @@ "version": "10.29.2", "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.2.tgz", "integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==", - "dev": true, "license": "MIT", "funding": { "type": "opencollective", @@ -5210,7 +5183,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -5222,7 +5194,6 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, "node_modules/punycode": { @@ -5239,7 +5210,6 @@ "version": "19.2.7", "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", - "dev": true, "license": "MIT", "peer": true, "engines": { @@ -5260,14 +5230,13 @@ "react": "^19.2.7" } }, - "node_modules/react-force-graph-2d": { + "node_modules/react-force-graph-3d": { "version": "1.29.1", - "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.29.1.tgz", - "integrity": "sha512-1Rl/1Z3xy2iTHKj6a0jRXGyiI86xUti81K+jBQZ+Oe46csaMikp47L5AjrzA9hY9fNGD63X8ffrqnvaORukCuQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/react-force-graph-3d/-/react-force-graph-3d-1.29.1.tgz", + "integrity": "sha512-5Vp+PGpYnO+zLwgK2NvNqdXHvsWLrFzpDfJW1vUA1twjo9SPvXqfUYQrnRmAbD+K2tOxkZw1BkbH31l5b4TWHg==", "license": "MIT", "dependencies": { - "force-graph": "^1.51", + "3d-force-graph": "^1.79", "prop-types": "15", "react-kapsule": "^2.5" }, @@ -5289,7 +5258,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.6.0.tgz", "integrity": "sha512-HzLJoYb1n1kfwjXbqFFcRR0EA6oPsJ64tNdDmCSaL/bz2o9wUZRSb0cMe//grLFeF9EVoL4CD/e6ozLyzEv+PQ==", - "dev": true, "license": "MIT", "dependencies": { "jerrypick": "^1.1.2" @@ -5583,6 +5551,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "dev": true, "license": "MIT" }, "node_modules/supports-color": { @@ -5621,6 +5590,56 @@ "url": "https://opencollective.com/synckit" } }, + "node_modules/three": { + "version": "0.184.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.184.0.tgz", + "integrity": "sha512-wtTRjG92pM5eUg/KuUnHsqSAlPM296brTOcLgMRqEeylYTh/CdtvKUvCyyCQTzFuStieWxvZb8mVTMvdPyUpxg==", + "license": "MIT", + "peer": true + }, + "node_modules/three-forcegraph": { + "version": "1.43.4", + "resolved": "https://registry.npmjs.org/three-forcegraph/-/three-forcegraph-1.43.4.tgz", + "integrity": "sha512-FtmiZP/T16ZQaHza3JDaDn0YTXFtg9e7pGnTeU8nzu0NNkx7MpWbF/GvmpbQsWHx3rukHtkRv1fTorLPB3FDEA==", + "license": "MIT", + "dependencies": { + "accessor-fn": "1", + "d3-array": "1 - 3", + "d3-force-3d": "2 - 3", + "d3-scale": "1 - 4", + "d3-scale-chromatic": "1 - 3", + "data-bind-mapper": "1", + "kapsule": "^1.16", + "ngraph.forcelayout": "3", + "ngraph.graph": "20", + "tinycolor2": "1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "three": ">=0.118.3" + } + }, + "node_modules/three-render-objects": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/three-render-objects/-/three-render-objects-1.42.0.tgz", + "integrity": "sha512-KYfkPrYGEbIK8ChFocWqOF1aAN80FBUBWVYB8mB2oBpVuVN+52FvvngVYB5ieFANQu7Rt21rPYZ/xKaAgVWWRQ==", + "license": "MIT", + "dependencies": { + "@tweenjs/tween.js": "18 - 25", + "accessor-fn": "1", + "float-tooltip": "^1.7", + "kapsule": "^1.16", + "polished": "4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "three": ">=0.179" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -5632,7 +5651,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "dev": true, "license": "MIT" }, "node_modules/tinyexec": { @@ -5735,7 +5753,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD", "optional": true }, @@ -6023,6 +6040,7 @@ "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "dev": true, "license": "MIT" }, "node_modules/w3c-xmlserializer": { diff --git a/package.json b/package.json index b86fc55..cf404ca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "papercache", "private": true, - "version": "0.5.2", + "version": "0.5.3", "type": "module", "scripts": { "dev": "vite", @@ -33,10 +33,15 @@ "@tauri-apps/plugin-dialog": "^2.7.1", "@tauri-apps/plugin-fs": "^2.5.1", "@tauri-apps/plugin-global-shortcut": "^2.3.2", + "@tauri-apps/plugin-notification": "^2.3.3", "@tauri-apps/plugin-shell": "^2.3.5", "@tauri-apps/plugin-updater": "^2.10.1", "@tauri-apps/plugin-window-state": "^2.4.1", - "expr-eval": "^2.0.2" + "@types/d3-force": "^3.0.10", + "d3-force": "^3.0.0", + "expr-eval": "^2.0.2", + "react-force-graph-3d": "^1.29.1", + "three": "^0.184.0" }, "devDependencies": { "@codemirror/commands": "^6.10.3", @@ -70,11 +75,14 @@ "prettier": "^3.8.3", "react": "^19.2.6", "react-dom": "^19.2.6", - "react-force-graph-2d": "^1.29.1", "typescript": "~6.0.2", "typescript-eslint": "^8.59.2", "vite": "^8.0.12", "vitest": "^4.1.7", "zustand": "^5.0.14" + }, + "optionalDependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1" } } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fb091d9..2cdab6b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -715,7 +715,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "typenum", ] @@ -2374,6 +2374,20 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "mac-notification-sys" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd604973958ddcc11b561193c0fb96ba146506ef2f231ef2e7c35fd2cbc9beca" +dependencies = [ + "cc", + "log", + "objc2", + "objc2-foundation", + "time", + "uuid", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2520,6 +2534,20 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "notify-rust" +version = "4.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b4c1b4f2aa9f25f63a7a49d3dd0ed567b3670da15330a66b29434be899b891" +dependencies = [ + "futures-lite", + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + [[package]] name = "num-conv" version = "0.2.2" @@ -2898,7 +2926,7 @@ dependencies = [ [[package]] name = "papercache" -version = "0.4.0" +version = "0.5.3" dependencies = [ "aes-gcm", "base64 0.22.1", @@ -2906,7 +2934,7 @@ dependencies = [ "dirs 5.0.1", "keyring", "objc", - "rand", + "rand 0.8.6", "reqwest 0.11.27", "serde", "serde_json", @@ -2915,6 +2943,7 @@ dependencies = [ "tauri-plugin-autostart", "tauri-plugin-dialog", "tauri-plugin-global-shortcut", + "tauri-plugin-notification", "tauri-plugin-opener", "tauri-plugin-updater", "tauri-plugin-window-state", @@ -3046,7 +3075,7 @@ checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" dependencies = [ "base64 0.22.1", "indexmap 2.14.0", - "quick-xml", + "quick-xml 0.39.4", "serde", "time", ] @@ -3201,6 +3230,15 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + [[package]] name = "quick-xml" version = "0.39.4" @@ -3238,8 +3276,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -3249,7 +3297,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -3261,6 +3319,15 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -4436,6 +4503,25 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "tauri-plugin-notification" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc" +dependencies = [ + "log", + "notify-rust", + "rand 0.9.4", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "thiserror 2.0.18", + "time", + "url", +] + [[package]] name = "tauri-plugin-opener" version = "2.5.4" @@ -4606,6 +4692,18 @@ dependencies = [ "toml 1.1.2+spec-1.1.0", ] +[[package]] +name = "tauri-winrt-notification" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9" +dependencies = [ + "quick-xml 0.37.5", + "thiserror 2.0.18", + "windows", + "windows-version", +] + [[package]] name = "tempfile" version = "3.27.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c5883ed..4e04991 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "papercache" -version = "0.4.0" +version = "0.5.3" description = "A PaperCache Tauri App" authors = ["Aditya Sharma"] edition = "2021" @@ -27,6 +27,7 @@ dirs = "5.0" aes-gcm = "0.10" rand = "0.8" base64 = "0.22" +tauri-plugin-notification = "2.0.0-rc.5" [target.'cfg(target_os = "macos")'.dependencies] cocoa = "0.25" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 2806c99..336b855 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -11,6 +11,7 @@ "window-state:default", "autostart:default", "updater:default", - "core:window:allow-start-dragging" + "core:window:allow-start-dragging", + "notification:default" ] } diff --git a/src-tauri/src/commands/fs.rs b/src-tauri/src/commands/fs.rs index f266997..975357c 100644 --- a/src-tauri/src/commands/fs.rs +++ b/src-tauri/src/commands/fs.rs @@ -197,54 +197,229 @@ pub fn set_dialog_open(state: tauri::State<'_, crate::DialogState>, open: bool) state.is_open.store(open, Ordering::SeqCst); } +fn write_onboarding_file(base: &Path, rel_path: &str, content: &str, _is_new_version: bool) { + let path = base.join(rel_path); + if let Some(parent) = path.parent() { + let _ = fs::create_dir_all(parent); + } + // Only write if file doesn't exist — preserve user edits across version changes + if !path.exists() { + let _ = fs::write(&path, content); + } +} + +#[tauri::command] +pub fn remove_onboarding_files() -> Result<(), String> { + if let Ok(base) = get_papercache_dir() { + // Only remove generated onboarding content — preserve Welcome.md and commands/ + let onboarding_dir = base.join("onboarding"); + let _ = fs::remove_dir_all(&onboarding_dir); + + let marker = base.join(".onboarding_version"); + let _ = fs::remove_file(&marker); + } + Ok(()) +} + pub fn run_onboarding(app: &AppHandle) { let is_hyprland = std::env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() || std::env::var("HYPRLAND_CMD").is_ok(); let mod_key = if is_hyprland { "Alt" } else { "Command/Ctrl" }; if let Ok(base) = get_papercache_dir() { - let welcome_path = base.join("Welcome.md"); - - let welcome_content = format!( - "# Welcome to PaperCache\n\nThis is your first note. Start typing to edit it, or use {} + Shift + N to create a new one!", - mod_key - ); - - if !welcome_path.exists() { - let _ = fs::write(&welcome_path, &welcome_content); - } else { - // Force update if the file contains the old generic shortcut text - if let Ok(content) = fs::read_to_string(&welcome_path) { - if content.contains("use shortcuts to create a new one!") || content.contains("Command/Ctrl + Shift + N") || content.contains("Alt + Shift + N") { - let _ = fs::write(&welcome_path, &welcome_content); - } - } + let version = app.package_info().version.to_string(); + let version_marker = base.join(".onboarding_version"); + let last_version = fs::read_to_string(&version_marker).ok(); + let is_new_version = last_version.as_deref() != Some(&version); + + if is_new_version { + let _ = fs::write(&version_marker, &version); } + let mk = mod_key; + + write_onboarding_file(&base, "Welcome.md", &format!( + "# Welcome to PaperCache\n\n\ + This is your first note. Start typing to edit it, or use **{0} + N** to create a new one. \ + PaperCache is a markdown-based knowledge manager with AI, graph visualization, tasks, timers, and more.\n\n\ + ## Quick Start\n\n\ + - **New note** — Press {0} + N (or {0} + Shift + N from anywhere)\n\ + - **Search notes** — Press {0} + P\n\ + - **Graph view** — Press {0} + G\n\ + - **Tasks & timers** — Press {0} + T\n\ + - **Settings** — Press {0} + Shift + S\n\n\ + ## Explore by Topic\n\n\ + - [Editor Features](/file onboarding/Editor.md) — Markdown, highlights, tags, pills, math, variables\n\ + - [Slash Commands](/file onboarding/Commands.md) — AI, tasks, checkboxes, timers, variables\n\ + - [Keyboard Shortcuts](/file Shortcuts.md) — Complete reference\n\ + - [Graph View](/file onboarding/Graph.md) — Knowledge graph visualization\n\ + - [AI Features](/file onboarding/AI.md) — Configuration and usage\n\ + - [Tasks & Timers](/file onboarding/Tasks.md) — Task management and countdowns\n\ + - [Customization & System](/file onboarding/Customization.md) — Themes, settings, system features\n\n\ + Press **{0} + Click** on any link above to jump to that note. \ + Or start typing to edit this one!", + mk + ), is_new_version); + + write_onboarding_file(&base, "onboarding/Editor.md", &format!( + "# Editor Features\n\n\ + PaperCache uses a full-featured markdown editor with these capabilities:\n\n\ + ## Markdown\n\n\ + Headings (H1-H6), bold, italic, strikethrough, lists, horizontal rules (`---`), \ + and fenced code blocks with language labels and one-click copy.\n\n\ + ## Highlights\n\n\ + Select text and press **{0} + H** to wrap it in `==text==` which renders as a visual highlight.\n\n\ + ## Tags\n\n\ + Type `!tagname` anywhere in your note. Tags appear as clickable pills \ + in the search view — right-click for bulk delete or export.\n\n\ + ## Color Pills\n\n\ + Hex colors like `#D97757` auto-render as a colored swatch. Click the circle to copy the hex code.\n\n\ + ## Date & Time Pills\n\n\ + `DD-MM-YYYY` and `HH:MM` formats auto-highlight for easy scanning.\n\n\ + ## Currency Pills\n\n\ + `$100`, `€50`, `£20`, `¥1000`, `₹500` auto-detect.\n\n\ + ## Reactive Math\n\n\ + Type an equation ending with `=` like `2+2=` and the result appears instantly. \ + Supports any arithmetic expression via `expr-eval`.\n\n\ + ## Variables\n\n\ + - `/var name = value` defines a note-scoped variable. Refer to it elsewhere and it auto-updates.\n\ + - `/globvar name = value` defines a cross-note global variable visible in all notes.\n\ + - Changing any variable re-evaluates all dependent math expressions.\n\n\ + ## Note Management\n\n\ + - **Auto-title** — The first `# Header` in a note becomes its display title\n\ + - **Rename** — Click the title bar to rename; changes the file ID\n\ + - **Internal links** — `[text](/file NoteTitle.md)` — {0} + Click to jump\n\ + - **External links** — `[text](url)` — {0} + Click to open in browser\n\ + - **Folders** — Use `/` in note names (e.g. `projects/my-note.md`) for nested folders with distinct colors\n\ + - **Delete** — {0} + Backspace with confirmation\n\n\ + ---\n\ + ↑ [Welcome](/file Welcome.md) → [Slash Commands](/file onboarding/Commands.md)", + mk + ), is_new_version); + + write_onboarding_file(&base, "onboarding/Commands.md", + "# Slash Commands\n\n\ + Type `/` in the editor to trigger autocomplete, then press Tab to accept. \ + Press Enter to execute.\n\n\ + ## Available Commands\n\n\ + - `/ai ` — Inline AI completion. Makes an API call and inserts the response.\n\ + - `/ctx ` — AI with full note context (up to 50,000 chars). Same as `/context`.\n\ + - `/context ` — Alias for `/ctx`.\n\ + - `/task