a very good jj gui
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: consolidate Tauri mocks into single setup module

+1023 -352
+39 -23
apps/desktop/src/main.tsx
··· 1 + // MUST be first import - sets up Tauri stub for browser mode 2 + import { IS_TAURI } from "./tauri-stub"; 3 + 1 4 import { RegistryProvider } from "@effect-atom/atom-react"; 2 5 import { WorkerPoolContextProvider } from "@pierre/diffs/react"; 3 6 import { QueryClientProvider } from "@tanstack/react-query"; 4 7 import { createRouter, RouterProvider } from "@tanstack/react-router"; 5 - import { getCurrent, onOpenUrl } from "@tauri-apps/plugin-deep-link"; 6 8 import React from "react"; 7 9 import ReactDOM from "react-dom/client"; 8 10 import { queryClient } from "./db"; 9 11 import { initializeTheme } from "./hooks/useTheme"; 12 + import { setupMocks } from "./mocks/setup"; 10 13 import { routeTree } from "./routeTree.gen"; 11 14 import "./styles/index.css"; 12 15 ··· 24 27 routeTree, 25 28 defaultPreloadStaleTime: 0, 26 29 scrollRestoration: false, 30 + defaultStructuralSharing: true, 27 31 }); 28 32 29 33 function handleDeepLinks(urls: string[]) { ··· 47 51 } 48 52 } 49 53 50 - // Handle deep links passed on cold start 51 - getCurrent().then((urls) => { 54 + async function setupDeepLinks(): Promise<void> { 55 + if (!IS_TAURI) return; 56 + 57 + const { getCurrent, onOpenUrl } = await import("@tauri-apps/plugin-deep-link"); 58 + 59 + // Handle deep links passed on cold start 60 + const urls = await getCurrent(); 52 61 if (urls) { 53 62 handleDeepLinks(urls); 54 63 } 55 - }); 56 64 57 - // Handle deep links when app is already running 58 - onOpenUrl(handleDeepLinks); 65 + // Handle deep links when app is already running 66 + onOpenUrl(handleDeepLinks); 67 + } 59 68 60 69 declare module "@tanstack/react-router" { 61 70 interface Register { ··· 63 72 } 64 73 } 65 74 66 - initializeTheme(); 75 + async function bootstrap(): Promise<void> { 76 + await setupMocks(); 77 + await setupDeepLinks(); 67 78 68 - const root = document.getElementById("root"); 69 - if (root) { 70 - ReactDOM.createRoot(root).render( 71 - <React.StrictMode> 72 - <RegistryProvider> 73 - <QueryClientProvider client={queryClient}> 74 - <WorkerPoolContextProvider 75 - poolOptions={workerPoolOptions} 76 - highlighterOptions={highlighterOptions} 77 - > 78 - <RouterProvider router={router} /> 79 - </WorkerPoolContextProvider> 80 - </QueryClientProvider> 81 - </RegistryProvider> 82 - </React.StrictMode>, 83 - ); 79 + initializeTheme(); 80 + 81 + const root = document.getElementById("root"); 82 + if (root) { 83 + ReactDOM.createRoot(root).render( 84 + <React.StrictMode> 85 + <RegistryProvider> 86 + <QueryClientProvider client={queryClient}> 87 + <WorkerPoolContextProvider 88 + poolOptions={workerPoolOptions} 89 + highlighterOptions={highlighterOptions} 90 + > 91 + <RouterProvider router={router} /> 92 + </WorkerPoolContextProvider> 93 + </QueryClientProvider> 94 + </RegistryProvider> 95 + </React.StrictMode>, 96 + ); 97 + } 84 98 } 99 + 100 + bootstrap();
+970
apps/desktop/src/mocks/setup.ts
··· 1 + // Runtime mock setup - patches invoke when not running in Tauri 2 + // NOTE: tauri-stub.ts must be imported before this to set up __TAURI_INTERNALS__ 3 + 4 + import { IS_TAURI } from "@/tauri-stub"; 5 + import type { Revision, WorkingCopyStatus, Repository, ChangedFile } from "@/schemas"; 6 + 7 + // Generate random jj-style change ID (12 characters, k-z only) 8 + function generateChangeId(): string { 9 + const chars = "klmnopqrstuvwxyz"; 10 + let result = ""; 11 + for (let i = 0; i < 12; i++) { 12 + result += chars[Math.floor(Math.random() * chars.length)]; 13 + } 14 + return result; 15 + } 16 + 17 + // Calculate shortest unique prefix for each change ID 18 + function calculateShortIds(revisionsRaw: Omit<Revision, "change_id_short">[]): Revision[] { 19 + const changeIds = revisionsRaw.map((r) => r.change_id); 20 + const result: Revision[] = []; 21 + 22 + for (let i = 0; i < changeIds.length; i++) { 23 + const changeId = changeIds[i]; 24 + let prefixLen = 1; 25 + 26 + // Find minimum prefix length that's unique 27 + while (prefixLen <= changeId.length) { 28 + const prefix = changeId.slice(0, prefixLen); 29 + const matches = changeIds.filter((id) => id.startsWith(prefix)); 30 + 31 + // Check if this prefix is unique (only matches this change ID) 32 + if (matches.length === 1) { 33 + break; 34 + } 35 + 36 + prefixLen++; 37 + } 38 + 39 + // Handle divergent commits 40 + const revision = revisionsRaw[i]; 41 + let changeIdShort: string; 42 + if (revision.is_divergent && revision.divergent_index !== null) { 43 + changeIdShort = `${changeId.slice(0, prefixLen)}/${revision.divergent_index}`; 44 + } else { 45 + changeIdShort = changeId.slice(0, prefixLen); 46 + } 47 + 48 + result.push({ 49 + ...revision, 50 + change_id_short: changeIdShort, 51 + }); 52 + } 53 + 54 + return result; 55 + } 56 + 57 + let mockProjects: Repository[] = [ 58 + { 59 + id: "mock-1", 60 + path: "/Users/demo/projects/tatami", 61 + name: "tatami", 62 + last_opened_at: Date.now(), 63 + revset_preset: null, 64 + }, 65 + { 66 + id: "mock-2", 67 + path: "/Users/demo/projects/example", 68 + name: "example", 69 + last_opened_at: Date.now() - 86400000, 70 + revset_preset: null, 71 + }, 72 + ]; 73 + 74 + // Complex mock revision graph representing realistic development workflow 75 + // Structure: Multiple unmerged feature branches with 3+ commits, diverse branching patterns 76 + // Change IDs are generated randomly (jj-style: 12 chars, k-z only) 77 + // Short IDs are calculated as minimum unique prefixes 78 + // Only one "main" bookmark exists on the latest main commit 79 + const mockRevisionsRaw: Omit<Revision, "change_id_short">[] = [ 80 + // Root commit 81 + { 82 + commit_id: "root0000000000", 83 + change_id: generateChangeId(), 84 + parent_ids: [], 85 + parent_edges: [], 86 + description: "chore: initial commit", 87 + author: "alice@example.com", 88 + timestamp: new Date(Date.now() - 2592000000).toISOString(), // 30 days ago 89 + is_working_copy: false, 90 + is_immutable: true, 91 + is_mine: false, 92 + is_trunk: false, 93 + is_divergent: false, 94 + divergent_index: null, 95 + bookmarks: [], 96 + }, 97 + // Main trunk commits 98 + { 99 + commit_id: "main0010000000", 100 + change_id: generateChangeId(), 101 + parent_ids: ["root0000000000"], 102 + parent_edges: [{ parent_id: "root0000000000", edge_type: "direct" }], 103 + description: "feat: initial project setup with build config", 104 + author: "alice@example.com", 105 + timestamp: new Date(Date.now() - 2500000000).toISOString(), 106 + is_working_copy: false, 107 + is_immutable: true, 108 + is_mine: false, 109 + is_trunk: true, 110 + is_divergent: false, 111 + divergent_index: null, 112 + bookmarks: [], 113 + }, 114 + { 115 + commit_id: "main0020000000", 116 + change_id: generateChangeId(), 117 + parent_ids: ["main0010000000"], 118 + parent_edges: [{ parent_id: "main0010000000", edge_type: "direct" }], 119 + description: "feat: add basic routing infrastructure", 120 + author: "alice@example.com", 121 + timestamp: new Date(Date.now() - 2400000000).toISOString(), 122 + is_working_copy: false, 123 + is_immutable: true, 124 + is_mine: false, 125 + is_trunk: true, 126 + is_divergent: false, 127 + divergent_index: null, 128 + bookmarks: [], 129 + }, 130 + { 131 + commit_id: "main0030000000", 132 + change_id: generateChangeId(), 133 + parent_ids: ["main0020000000"], 134 + parent_edges: [{ parent_id: "main0020000000", edge_type: "direct" }], 135 + description: "feat: implement core data models", 136 + author: "bob@example.com", 137 + timestamp: new Date(Date.now() - 2300000000).toISOString(), 138 + is_working_copy: false, 139 + is_immutable: true, 140 + is_mine: false, 141 + is_trunk: true, 142 + is_divergent: false, 143 + divergent_index: null, 144 + bookmarks: [], 145 + }, 146 + // Feature branch A: Authentication (branches from main003, 4 commits - UNMERGED) 147 + { 148 + commit_id: "auth0010000000", 149 + change_id: generateChangeId(), 150 + parent_ids: ["main0030000000"], 151 + parent_edges: [{ parent_id: "main0030000000", edge_type: "direct" }], 152 + description: "feat: add authentication service skeleton", 153 + author: "alice@example.com", 154 + timestamp: new Date(Date.now() - 2200000000).toISOString(), 155 + is_working_copy: false, 156 + is_immutable: false, 157 + is_mine: true, 158 + is_trunk: false, 159 + is_divergent: false, 160 + divergent_index: null, 161 + bookmarks: ["feature/auth"], 162 + }, 163 + { 164 + commit_id: "auth0020000000", 165 + change_id: generateChangeId(), 166 + parent_ids: ["auth0010000000"], 167 + parent_edges: [{ parent_id: "auth0010000000", edge_type: "direct" }], 168 + description: "feat: implement login form component", 169 + author: "alice@example.com", 170 + timestamp: new Date(Date.now() - 2100000000).toISOString(), 171 + is_working_copy: false, 172 + is_immutable: false, 173 + is_mine: true, 174 + is_trunk: false, 175 + is_divergent: false, 176 + divergent_index: null, 177 + bookmarks: [], 178 + }, 179 + { 180 + commit_id: "auth0030000000", 181 + change_id: generateChangeId(), 182 + parent_ids: ["auth0020000000"], 183 + parent_edges: [{ parent_id: "auth0020000000", edge_type: "direct" }], 184 + description: "feat: add JWT token handling", 185 + author: "alice@example.com", 186 + timestamp: new Date(Date.now() - 2000000000).toISOString(), 187 + is_working_copy: false, 188 + is_immutable: false, 189 + is_mine: true, 190 + is_trunk: false, 191 + is_divergent: false, 192 + divergent_index: null, 193 + bookmarks: [], 194 + }, 195 + { 196 + commit_id: "auth0040000000", 197 + change_id: generateChangeId(), 198 + parent_ids: ["auth0030000000"], 199 + parent_edges: [{ parent_id: "auth0030000000", edge_type: "direct" }], 200 + description: "feat: add password reset flow", 201 + author: "alice@example.com", 202 + timestamp: new Date(Date.now() - 1900000000).toISOString(), 203 + is_working_copy: false, 204 + is_immutable: false, 205 + is_mine: true, 206 + is_trunk: false, 207 + is_divergent: false, 208 + divergent_index: null, 209 + bookmarks: [], 210 + }, 211 + // Feature branch B: Dark mode (branches from main003, 5 commits - UNMERGED) 212 + { 213 + commit_id: "dark0010000000", 214 + change_id: generateChangeId(), 215 + parent_ids: ["main0030000000"], 216 + parent_edges: [{ parent_id: "main0030000000", edge_type: "direct" }], 217 + description: "feat: add theme provider infrastructure", 218 + author: "charlie@example.com", 219 + timestamp: new Date(Date.now() - 2150000000).toISOString(), 220 + is_working_copy: false, 221 + is_immutable: false, 222 + is_mine: false, 223 + is_trunk: false, 224 + is_divergent: false, 225 + divergent_index: null, 226 + bookmarks: ["feature/dark-mode"], 227 + }, 228 + { 229 + commit_id: "dark0020000000", 230 + change_id: generateChangeId(), 231 + parent_ids: ["dark0010000000"], 232 + parent_edges: [{ parent_id: "dark0010000000", edge_type: "direct" }], 233 + description: "feat: implement dark mode toggle component", 234 + author: "charlie@example.com", 235 + timestamp: new Date(Date.now() - 2050000000).toISOString(), 236 + is_working_copy: false, 237 + is_immutable: false, 238 + is_mine: false, 239 + is_trunk: false, 240 + is_divergent: false, 241 + divergent_index: null, 242 + bookmarks: [], 243 + }, 244 + { 245 + commit_id: "dark0030000000", 246 + change_id: generateChangeId(), 247 + parent_ids: ["dark0020000000"], 248 + parent_edges: [{ parent_id: "dark0020000000", edge_type: "direct" }], 249 + description: "feat: add dark mode styles for all components", 250 + author: "charlie@example.com", 251 + timestamp: new Date(Date.now() - 1950000000).toISOString(), 252 + is_working_copy: false, 253 + is_immutable: false, 254 + is_mine: false, 255 + is_trunk: false, 256 + is_divergent: false, 257 + divergent_index: null, 258 + bookmarks: [], 259 + }, 260 + { 261 + commit_id: "dark0040000000", 262 + change_id: generateChangeId(), 263 + parent_ids: ["dark0030000000"], 264 + parent_edges: [{ parent_id: "dark0030000000", edge_type: "direct" }], 265 + description: "feat: add system theme detection", 266 + author: "charlie@example.com", 267 + timestamp: new Date(Date.now() - 1850000000).toISOString(), 268 + is_working_copy: false, 269 + is_immutable: false, 270 + is_mine: false, 271 + is_trunk: false, 272 + is_divergent: false, 273 + divergent_index: null, 274 + bookmarks: [], 275 + }, 276 + { 277 + commit_id: "dark0050000000", 278 + change_id: generateChangeId(), 279 + parent_ids: ["dark0040000000"], 280 + parent_edges: [{ parent_id: "dark0040000000", edge_type: "direct" }], 281 + description: "fix: improve contrast ratios for accessibility", 282 + author: "charlie@example.com", 283 + timestamp: new Date(Date.now() - 1750000000).toISOString(), 284 + is_working_copy: false, 285 + is_immutable: false, 286 + is_mine: false, 287 + is_trunk: false, 288 + is_divergent: false, 289 + divergent_index: null, 290 + bookmarks: [], 291 + }, 292 + // Main trunk continues 293 + { 294 + commit_id: "main0040000000", 295 + change_id: generateChangeId(), 296 + parent_ids: ["main0030000000"], 297 + parent_edges: [{ parent_id: "main0030000000", edge_type: "direct" }], 298 + description: "fix: resolve race condition in data fetching", 299 + author: "bob@example.com", 300 + timestamp: new Date(Date.now() - 1800000000).toISOString(), 301 + is_working_copy: false, 302 + is_immutable: true, 303 + is_mine: false, 304 + is_trunk: true, 305 + is_divergent: false, 306 + divergent_index: null, 307 + bookmarks: [], 308 + }, 309 + { 310 + commit_id: "main0050000000", 311 + change_id: generateChangeId(), 312 + parent_ids: ["main0040000000"], 313 + parent_edges: [{ parent_id: "main0040000000", edge_type: "direct" }], 314 + description: "refactor: extract shared utilities into separate module", 315 + author: "bob@example.com", 316 + timestamp: new Date(Date.now() - 1700000000).toISOString(), 317 + is_working_copy: false, 318 + is_immutable: true, 319 + is_mine: false, 320 + is_trunk: true, 321 + is_divergent: false, 322 + divergent_index: null, 323 + bookmarks: [], 324 + }, 325 + // Feature branch C: Performance (branches from main005, 4 commits - UNMERGED) 326 + { 327 + commit_id: "perf0010000000", 328 + change_id: generateChangeId(), 329 + parent_ids: ["main0050000000"], 330 + parent_edges: [{ parent_id: "main0050000000", edge_type: "direct" }], 331 + description: "perf: optimize database queries", 332 + author: "david@example.com", 333 + timestamp: new Date(Date.now() - 1600000000).toISOString(), 334 + is_working_copy: false, 335 + is_immutable: false, 336 + is_mine: false, 337 + is_trunk: false, 338 + is_divergent: false, 339 + divergent_index: null, 340 + bookmarks: ["feature/performance"], 341 + }, 342 + { 343 + commit_id: "perf0020000000", 344 + change_id: generateChangeId(), 345 + parent_ids: ["perf0010000000"], 346 + parent_edges: [{ parent_id: "perf0010000000", edge_type: "direct" }], 347 + description: "perf: add query result caching layer", 348 + author: "david@example.com", 349 + timestamp: new Date(Date.now() - 1500000000).toISOString(), 350 + is_working_copy: false, 351 + is_immutable: false, 352 + is_mine: false, 353 + is_trunk: false, 354 + is_divergent: false, 355 + divergent_index: null, 356 + bookmarks: [], 357 + }, 358 + { 359 + commit_id: "perf0030000000", 360 + change_id: generateChangeId(), 361 + parent_ids: ["perf0020000000"], 362 + parent_edges: [{ parent_id: "perf0020000000", edge_type: "direct" }], 363 + description: "perf: implement lazy loading for large datasets", 364 + author: "david@example.com", 365 + timestamp: new Date(Date.now() - 1400000000).toISOString(), 366 + is_working_copy: false, 367 + is_immutable: false, 368 + is_mine: false, 369 + is_trunk: false, 370 + is_divergent: false, 371 + divergent_index: null, 372 + bookmarks: [], 373 + }, 374 + { 375 + commit_id: "perf0040000000", 376 + change_id: generateChangeId(), 377 + parent_ids: ["perf0030000000"], 378 + parent_edges: [{ parent_id: "perf0030000000", edge_type: "direct" }], 379 + description: "perf: add connection pooling for database", 380 + author: "david@example.com", 381 + timestamp: new Date(Date.now() - 1300000000).toISOString(), 382 + is_working_copy: false, 383 + is_immutable: false, 384 + is_mine: false, 385 + is_trunk: false, 386 + is_divergent: false, 387 + divergent_index: null, 388 + bookmarks: [], 389 + }, 390 + // Main trunk continues 391 + { 392 + commit_id: "main0060000000", 393 + change_id: generateChangeId(), 394 + parent_ids: ["main0050000000"], 395 + parent_edges: [{ parent_id: "main0050000000", edge_type: "direct" }], 396 + description: "docs: update API documentation", 397 + author: "alice@example.com", 398 + timestamp: new Date(Date.now() - 1200000000).toISOString(), 399 + is_working_copy: false, 400 + is_immutable: true, 401 + is_mine: false, 402 + is_trunk: true, 403 + is_divergent: false, 404 + divergent_index: null, 405 + bookmarks: [], 406 + }, 407 + { 408 + commit_id: "main0070000000", 409 + change_id: generateChangeId(), 410 + parent_ids: ["main0060000000"], 411 + parent_edges: [{ parent_id: "main0060000000", edge_type: "direct" }], 412 + description: "chore: update dependencies", 413 + author: "bob@example.com", 414 + timestamp: new Date(Date.now() - 1100000000).toISOString(), 415 + is_working_copy: false, 416 + is_immutable: true, 417 + is_mine: false, 418 + is_trunk: true, 419 + is_divergent: false, 420 + divergent_index: null, 421 + bookmarks: [], 422 + }, 423 + // Feature branch D: API improvements (branches from main007, 3 commits - UNMERGED) 424 + { 425 + commit_id: "api0010000000", 426 + change_id: generateChangeId(), 427 + parent_ids: ["main0070000000"], 428 + parent_edges: [{ parent_id: "main0070000000", edge_type: "direct" }], 429 + description: "feat: add REST API endpoint for user management", 430 + author: "eve@example.com", 431 + timestamp: new Date(Date.now() - 1000000000).toISOString(), 432 + is_working_copy: false, 433 + is_immutable: false, 434 + is_mine: false, 435 + is_trunk: false, 436 + is_divergent: false, 437 + divergent_index: null, 438 + bookmarks: ["feature/api"], 439 + }, 440 + { 441 + commit_id: "api0020000000", 442 + change_id: generateChangeId(), 443 + parent_ids: ["api0010000000"], 444 + parent_edges: [{ parent_id: "api0010000000", edge_type: "direct" }], 445 + description: "feat: add request validation middleware", 446 + author: "eve@example.com", 447 + timestamp: new Date(Date.now() - 900000000).toISOString(), 448 + is_working_copy: false, 449 + is_immutable: false, 450 + is_mine: false, 451 + is_trunk: false, 452 + is_divergent: false, 453 + divergent_index: null, 454 + bookmarks: [], 455 + }, 456 + { 457 + commit_id: "api0030000000", 458 + change_id: generateChangeId(), 459 + parent_ids: ["api0020000000"], 460 + parent_edges: [{ parent_id: "api0020000000", edge_type: "direct" }], 461 + description: "feat: add pagination support for list endpoints", 462 + author: "eve@example.com", 463 + timestamp: new Date(Date.now() - 800000000).toISOString(), 464 + is_working_copy: false, 465 + is_immutable: false, 466 + is_mine: false, 467 + is_trunk: false, 468 + is_divergent: false, 469 + divergent_index: null, 470 + bookmarks: [], 471 + }, 472 + // Feature branch E: Testing (branches from main007, 5 commits - UNMERGED) 473 + { 474 + commit_id: "test0010000000", 475 + change_id: generateChangeId(), 476 + parent_ids: ["main0070000000"], 477 + parent_edges: [{ parent_id: "main0070000000", edge_type: "direct" }], 478 + description: "test: add unit tests for core utilities", 479 + author: "frank@example.com", 480 + timestamp: new Date(Date.now() - 950000000).toISOString(), 481 + is_working_copy: false, 482 + is_immutable: false, 483 + is_mine: false, 484 + is_trunk: false, 485 + is_divergent: false, 486 + divergent_index: null, 487 + bookmarks: ["feature/testing"], 488 + }, 489 + { 490 + commit_id: "test0020000000", 491 + change_id: generateChangeId(), 492 + parent_ids: ["test0010000000"], 493 + parent_edges: [{ parent_id: "test0010000000", edge_type: "direct" }], 494 + description: "test: add integration tests for API endpoints", 495 + author: "frank@example.com", 496 + timestamp: new Date(Date.now() - 850000000).toISOString(), 497 + is_working_copy: false, 498 + is_immutable: false, 499 + is_mine: false, 500 + is_trunk: false, 501 + is_divergent: false, 502 + divergent_index: null, 503 + bookmarks: [], 504 + }, 505 + { 506 + commit_id: "test0030000000", 507 + change_id: generateChangeId(), 508 + parent_ids: ["test0020000000"], 509 + parent_edges: [{ parent_id: "test0020000000", edge_type: "direct" }], 510 + description: "test: add end-to-end tests for critical flows", 511 + author: "frank@example.com", 512 + timestamp: new Date(Date.now() - 750000000).toISOString(), 513 + is_working_copy: false, 514 + is_immutable: false, 515 + is_mine: false, 516 + is_trunk: false, 517 + is_divergent: false, 518 + divergent_index: null, 519 + bookmarks: [], 520 + }, 521 + { 522 + commit_id: "test0040000000", 523 + change_id: generateChangeId(), 524 + parent_ids: ["test0030000000"], 525 + parent_edges: [{ parent_id: "test0030000000", edge_type: "direct" }], 526 + description: "test: add performance benchmarks", 527 + author: "frank@example.com", 528 + timestamp: new Date(Date.now() - 650000000).toISOString(), 529 + is_working_copy: false, 530 + is_immutable: false, 531 + is_mine: false, 532 + is_trunk: false, 533 + is_divergent: false, 534 + divergent_index: null, 535 + bookmarks: [], 536 + }, 537 + { 538 + commit_id: "test0050000000", 539 + change_id: generateChangeId(), 540 + parent_ids: ["test0040000000"], 541 + parent_edges: [{ parent_id: "test0040000000", edge_type: "direct" }], 542 + description: "test: add test coverage reporting", 543 + author: "frank@example.com", 544 + timestamp: new Date(Date.now() - 550000000).toISOString(), 545 + is_working_copy: false, 546 + is_immutable: false, 547 + is_mine: false, 548 + is_trunk: false, 549 + is_divergent: false, 550 + divergent_index: null, 551 + bookmarks: [], 552 + }, 553 + // Main trunk continues 554 + { 555 + commit_id: "main0080000000", 556 + change_id: generateChangeId(), 557 + parent_ids: ["main0070000000"], 558 + parent_edges: [{ parent_id: "main0070000000", edge_type: "direct" }], 559 + description: "fix: handle edge case in form validation", 560 + author: "henry@example.com", 561 + timestamp: new Date(Date.now() - 700000000).toISOString(), 562 + is_working_copy: false, 563 + is_immutable: true, 564 + is_mine: false, 565 + is_trunk: true, 566 + is_divergent: false, 567 + divergent_index: null, 568 + bookmarks: [], 569 + }, 570 + // Feature branch F: UI improvements (branches from main008, 4 commits - UNMERGED) 571 + { 572 + commit_id: "ui0010000000", 573 + change_id: generateChangeId(), 574 + parent_ids: ["main0080000000"], 575 + parent_edges: [{ parent_id: "main0080000000", edge_type: "direct" }], 576 + description: "feat: redesign navigation component", 577 + author: "grace@example.com", 578 + timestamp: new Date(Date.now() - 600000000).toISOString(), 579 + is_working_copy: false, 580 + is_immutable: false, 581 + is_mine: false, 582 + is_trunk: false, 583 + is_divergent: false, 584 + divergent_index: null, 585 + bookmarks: ["feature/ui"], 586 + }, 587 + { 588 + commit_id: "ui0020000000", 589 + change_id: generateChangeId(), 590 + parent_ids: ["ui0010000000"], 591 + parent_edges: [{ parent_id: "ui0010000000", edge_type: "direct" }], 592 + description: "feat: add responsive layout breakpoints", 593 + author: "grace@example.com", 594 + timestamp: new Date(Date.now() - 500000000).toISOString(), 595 + is_working_copy: false, 596 + is_immutable: false, 597 + is_mine: false, 598 + is_trunk: false, 599 + is_divergent: false, 600 + divergent_index: null, 601 + bookmarks: [], 602 + }, 603 + { 604 + commit_id: "ui0030000000", 605 + change_id: generateChangeId(), 606 + parent_ids: ["ui0020000000"], 607 + parent_edges: [{ parent_id: "ui0020000000", edge_type: "direct" }], 608 + description: "feat: add loading states and skeletons", 609 + author: "grace@example.com", 610 + timestamp: new Date(Date.now() - 400000000).toISOString(), 611 + is_working_copy: false, 612 + is_immutable: false, 613 + is_mine: false, 614 + is_trunk: false, 615 + is_divergent: false, 616 + divergent_index: null, 617 + bookmarks: [], 618 + }, 619 + { 620 + commit_id: "ui0040000000", 621 + change_id: generateChangeId(), 622 + parent_ids: ["ui0030000000"], 623 + parent_edges: [{ parent_id: "ui0030000000", edge_type: "direct" }], 624 + description: "feat: improve accessibility with ARIA labels", 625 + author: "grace@example.com", 626 + timestamp: new Date(Date.now() - 300000000).toISOString(), 627 + is_working_copy: false, 628 + is_immutable: false, 629 + is_mine: false, 630 + is_trunk: false, 631 + is_divergent: false, 632 + divergent_index: null, 633 + bookmarks: [], 634 + }, 635 + // Feature branch G: Security (branches from main008, 3 commits - UNMERGED) 636 + { 637 + commit_id: "sec0010000000", 638 + change_id: generateChangeId(), 639 + parent_ids: ["main0080000000"], 640 + parent_edges: [{ parent_id: "main0080000000", edge_type: "direct" }], 641 + description: "security: add input sanitization", 642 + author: "iris@example.com", 643 + timestamp: new Date(Date.now() - 550000000).toISOString(), 644 + is_working_copy: false, 645 + is_immutable: false, 646 + is_mine: false, 647 + is_trunk: false, 648 + is_divergent: false, 649 + divergent_index: null, 650 + bookmarks: ["feature/security"], 651 + }, 652 + { 653 + commit_id: "sec0020000000", 654 + change_id: generateChangeId(), 655 + parent_ids: ["sec0010000000"], 656 + parent_edges: [{ parent_id: "sec0010000000", edge_type: "direct" }], 657 + description: "security: implement rate limiting", 658 + author: "iris@example.com", 659 + timestamp: new Date(Date.now() - 450000000).toISOString(), 660 + is_working_copy: false, 661 + is_immutable: false, 662 + is_mine: false, 663 + is_trunk: false, 664 + is_divergent: false, 665 + divergent_index: null, 666 + bookmarks: [], 667 + }, 668 + { 669 + commit_id: "sec0030000000", 670 + change_id: generateChangeId(), 671 + parent_ids: ["sec0020000000"], 672 + parent_edges: [{ parent_id: "sec0020000000", edge_type: "direct" }], 673 + description: "security: add CSRF protection", 674 + author: "iris@example.com", 675 + timestamp: new Date(Date.now() - 350000000).toISOString(), 676 + is_working_copy: false, 677 + is_immutable: false, 678 + is_mine: false, 679 + is_trunk: false, 680 + is_divergent: false, 681 + divergent_index: null, 682 + bookmarks: [], 683 + }, 684 + // Feature branch H: Documentation (branches from main008, 4 commits - UNMERGED) 685 + { 686 + commit_id: "doc0010000000", 687 + change_id: generateChangeId(), 688 + parent_ids: ["main0080000000"], 689 + parent_edges: [{ parent_id: "main0080000000", edge_type: "direct" }], 690 + description: "docs: add architecture decision records", 691 + author: "lisa@example.com", 692 + timestamp: new Date(Date.now() - 480000000).toISOString(), 693 + is_working_copy: false, 694 + is_immutable: false, 695 + is_mine: false, 696 + is_trunk: false, 697 + is_divergent: false, 698 + divergent_index: null, 699 + bookmarks: ["feature/docs"], 700 + }, 701 + { 702 + commit_id: "doc0020000000", 703 + change_id: generateChangeId(), 704 + parent_ids: ["doc0010000000"], 705 + parent_edges: [{ parent_id: "doc0010000000", edge_type: "direct" }], 706 + description: "docs: add API reference documentation", 707 + author: "lisa@example.com", 708 + timestamp: new Date(Date.now() - 380000000).toISOString(), 709 + is_working_copy: false, 710 + is_immutable: false, 711 + is_mine: false, 712 + is_trunk: false, 713 + is_divergent: false, 714 + divergent_index: null, 715 + bookmarks: [], 716 + }, 717 + { 718 + commit_id: "doc0030000000", 719 + change_id: generateChangeId(), 720 + parent_ids: ["doc0020000000"], 721 + parent_edges: [{ parent_id: "doc0020000000", edge_type: "direct" }], 722 + description: "docs: add deployment guide", 723 + author: "lisa@example.com", 724 + timestamp: new Date(Date.now() - 280000000).toISOString(), 725 + is_working_copy: false, 726 + is_immutable: false, 727 + is_mine: false, 728 + is_trunk: false, 729 + is_divergent: false, 730 + divergent_index: null, 731 + bookmarks: [], 732 + }, 733 + { 734 + commit_id: "doc0040000000", 735 + change_id: generateChangeId(), 736 + parent_ids: ["doc0030000000"], 737 + parent_edges: [{ parent_id: "doc0030000000", edge_type: "direct" }], 738 + description: "docs: add troubleshooting section", 739 + author: "lisa@example.com", 740 + timestamp: new Date(Date.now() - 180000000).toISOString(), 741 + is_working_copy: false, 742 + is_immutable: false, 743 + is_mine: false, 744 + is_trunk: false, 745 + is_divergent: false, 746 + divergent_index: null, 747 + bookmarks: [], 748 + }, 749 + // Feature branch I: Monitoring (branches from main003, older branch - 3 commits - UNMERGED) 750 + { 751 + commit_id: "mon0010000000", 752 + change_id: generateChangeId(), 753 + parent_ids: ["main0030000000"], 754 + parent_edges: [{ parent_id: "main0030000000", edge_type: "direct" }], 755 + description: "feat: add application monitoring setup", 756 + author: "jack@example.com", 757 + timestamp: new Date(Date.now() - 2000000000).toISOString(), 758 + is_working_copy: false, 759 + is_immutable: false, 760 + is_mine: false, 761 + is_trunk: false, 762 + is_divergent: false, 763 + divergent_index: null, 764 + bookmarks: ["feature/monitoring"], 765 + }, 766 + { 767 + commit_id: "mon0020000000", 768 + change_id: generateChangeId(), 769 + parent_ids: ["mon0010000000"], 770 + parent_edges: [{ parent_id: "mon0010000000", edge_type: "direct" }], 771 + description: "feat: add error tracking integration", 772 + author: "jack@example.com", 773 + timestamp: new Date(Date.now() - 1900000000).toISOString(), 774 + is_working_copy: false, 775 + is_immutable: false, 776 + is_mine: false, 777 + is_trunk: false, 778 + is_divergent: false, 779 + divergent_index: null, 780 + bookmarks: [], 781 + }, 782 + { 783 + commit_id: "mon0030000000", 784 + change_id: generateChangeId(), 785 + parent_ids: ["mon0020000000"], 786 + parent_edges: [{ parent_id: "mon0020000000", edge_type: "direct" }], 787 + description: "feat: add performance metrics dashboard", 788 + author: "jack@example.com", 789 + timestamp: new Date(Date.now() - 1800000000).toISOString(), 790 + is_working_copy: false, 791 + is_immutable: false, 792 + is_mine: false, 793 + is_trunk: false, 794 + is_divergent: false, 795 + divergent_index: null, 796 + bookmarks: [], 797 + }, 798 + // Main trunk continues 799 + { 800 + commit_id: "main0090000000", 801 + change_id: generateChangeId(), 802 + parent_ids: ["main0080000000"], 803 + parent_edges: [{ parent_id: "main0080000000", edge_type: "direct" }], 804 + description: "fix: resolve memory leak in event handlers", 805 + author: "henry@example.com", 806 + timestamp: new Date(Date.now() - 200000000).toISOString(), 807 + is_working_copy: false, 808 + is_immutable: true, 809 + is_mine: false, 810 + is_trunk: true, 811 + is_divergent: false, 812 + divergent_index: null, 813 + bookmarks: [], 814 + }, 815 + // Current working copy (on main009) - only "main" bookmark exists here 816 + { 817 + commit_id: "main0100000000", 818 + change_id: generateChangeId(), 819 + parent_ids: ["main0090000000"], 820 + parent_edges: [{ parent_id: "main0090000000", edge_type: "direct" }], 821 + description: "chore: prepare for release", 822 + author: "alice@example.com", 823 + timestamp: new Date(Date.now() - 100000000).toISOString(), 824 + is_working_copy: false, 825 + is_immutable: true, 826 + is_mine: false, 827 + is_trunk: true, 828 + is_divergent: false, 829 + divergent_index: null, 830 + bookmarks: ["main"], // Only "main" bookmark 831 + }, 832 + // Current working copy (on main010) 833 + { 834 + commit_id: "wc00100000000", 835 + change_id: generateChangeId(), 836 + parent_ids: ["main0100000000"], 837 + parent_edges: [{ parent_id: "main0100000000", edge_type: "direct" }], 838 + description: "", 839 + author: "alice@example.com", 840 + timestamp: new Date().toISOString(), 841 + is_working_copy: true, 842 + is_immutable: false, 843 + is_mine: true, 844 + is_trunk: false, 845 + is_divergent: false, 846 + divergent_index: null, 847 + bookmarks: [], 848 + }, 849 + ]; 850 + 851 + // Calculate shortest unique prefixes for all change IDs 852 + const mockRevisions: Revision[] = calculateShortIds(mockRevisionsRaw); 853 + 854 + const mockChangedFiles: ChangedFile[] = [ 855 + { path: "src/main.rs", status: "modified" }, 856 + { path: "README.md", status: "added" }, 857 + ]; 858 + 859 + type MockHandler = (args: Record<string, unknown>) => unknown; 860 + 861 + const handlers: Record<string, MockHandler> = { 862 + get_projects: () => mockProjects, 863 + upsert_project: (args) => { 864 + const project = args.project as Repository; 865 + const existingIndex = mockProjects.findIndex((p) => p.id === project.id); 866 + if (existingIndex >= 0) { 867 + mockProjects[existingIndex] = project; 868 + } else { 869 + mockProjects = [project, ...mockProjects]; 870 + } 871 + return undefined; 872 + }, 873 + remove_project: (args) => { 874 + const projectId = args.projectId as string; 875 + mockProjects = mockProjects.filter((p) => p.id !== projectId); 876 + return undefined; 877 + }, 878 + find_project_by_path: (args) => { 879 + const path = args.path as string; 880 + return mockProjects.find((p) => p.path === path) ?? null; 881 + }, 882 + find_repository: () => "/Users/demo/projects/tatami", 883 + get_revisions: () => mockRevisions, 884 + get_status: (): WorkingCopyStatus => { 885 + const wc = mockRevisions.find((r) => r.is_working_copy); 886 + return { 887 + repo_path: "/Users/demo/projects/tatami", 888 + change_id: wc?.change_id ?? "klnmopqrstuv", 889 + files: mockChangedFiles, 890 + }; 891 + }, 892 + get_file_diff: (): string => `--- a/src/main.rs 893 + +++ b/src/main.rs 894 + @@ -1,3 +1,4 @@ 895 + fn main() { 896 + - println!("old"); 897 + + println!("new"); 898 + + println!("extra"); 899 + }`, 900 + get_revision_diff: (): string => `--- a/src/main.rs 901 + +++ b/src/main.rs 902 + @@ -1,3 +1,4 @@ 903 + fn main() { 904 + - println!("old"); 905 + + println!("new"); 906 + + println!("extra"); 907 + } 908 + --- a/README.md 909 + +++ b/README.md 910 + @@ -1,2 +1,3 @@ 911 + # Example Project 912 + +This is a new line 913 + Welcome to the project`, 914 + get_revision_changes: (): ChangedFile[] => mockChangedFiles, 915 + watch_repository: () => undefined, 916 + unwatch_repository: () => undefined, 917 + jj_new: () => undefined, 918 + jj_edit: () => undefined, 919 + jj_abandon: () => undefined, 920 + get_commit_recency: () => ({}), 921 + resolve_revset: (args) => { 922 + const revset = args.revset as string; 923 + // Simple mock implementation for common revsets 924 + if (revset === "@") { 925 + const wc = mockRevisions.find((r) => r.is_working_copy); 926 + return { change_ids: wc ? [wc.change_id] : [], error: null }; 927 + } 928 + if (revset === "@-") { 929 + const wc = mockRevisions.find((r) => r.is_working_copy); 930 + if (wc && wc.parent_ids.length > 0) { 931 + // Find parent by commit_id 932 + const parent = mockRevisions.find((r) => r.commit_id === wc.parent_ids[0]); 933 + return { change_ids: parent ? [parent.change_id] : [], error: null }; 934 + } 935 + return { change_ids: [], error: null }; 936 + } 937 + // Default: return all revisions (mock doesn't implement full revset) 938 + return { change_ids: mockRevisions.map((r) => r.change_id), error: null }; 939 + }, 940 + 941 + // Plugin commands 942 + "plugin:window|set_title": () => undefined, 943 + "plugin:event|listen": () => 0, // Returns listener ID 944 + "plugin:event|unlisten": () => undefined, 945 + "plugin:path|home_dir": () => "/Users/demo", 946 + "plugin:dialog|open": () => null, // User cancelled 947 + }; 948 + 949 + export async function setupMocks(): Promise<void> { 950 + if (IS_TAURI) { 951 + console.log("[Mocks] Running in Tauri, skipping mock setup"); 952 + return; 953 + } 954 + 955 + console.log("[Mocks] Not in Tauri, setting up IPC mocks..."); 956 + 957 + // Dynamically import to avoid loading in Tauri 958 + const { mockIPC } = await import("@tauri-apps/api/mocks"); 959 + 960 + mockIPC((cmd, args) => { 961 + const handler = handlers[cmd]; 962 + if (!handler) { 963 + console.warn(`[Mock] No handler for command: ${cmd}`, args); 964 + return undefined; 965 + } 966 + return handler((args ?? {}) as Record<string, unknown>); 967 + }); 968 + 969 + console.log("[Mocks] IPC mocks ready"); 970 + }
-276
apps/desktop/src/mocks/tauri-core.ts
··· 1 - // Mock invoke for browser development - swapped in by Vite when TAURI_DEV_HOST is not set 2 - 3 - interface ParentEdge { 4 - parent_id: string; 5 - edge_type: "direct" | "indirect" | "missing"; 6 - } 7 - 8 - interface Revision { 9 - commit_id: string; 10 - change_id: string; 11 - change_id_short: string; 12 - parent_ids: string[]; 13 - parent_edges: ParentEdge[]; 14 - description: string; 15 - author: string; 16 - timestamp: string; 17 - is_working_copy: boolean; 18 - is_immutable: boolean; 19 - is_mine: boolean; 20 - is_trunk: boolean; 21 - bookmarks: string[]; 22 - } 23 - 24 - interface Project { 25 - id: string; 26 - path: string; 27 - name: string; 28 - last_opened_at: number; 29 - revset_preset: string | null; 30 - } 31 - 32 - interface WorkingCopyStatus { 33 - repo_path: string; 34 - change_id: string; 35 - files: { path: string; status: "added" | "modified" | "deleted" }[]; 36 - } 37 - 38 - let mockProjects: Project[] = [ 39 - { 40 - id: "mock-1", 41 - path: "/Users/demo/projects/tatami", 42 - name: "tatami", 43 - last_opened_at: Date.now(), 44 - revset_preset: null, 45 - }, 46 - { 47 - id: "mock-2", 48 - path: "/Users/demo/projects/example", 49 - name: "example", 50 - last_opened_at: Date.now() - 86400000, 51 - revset_preset: null, 52 - }, 53 - ]; 54 - 55 - const mockRevisions: Revision[] = [ 56 - { 57 - commit_id: "a1b2c3d4e5f6", 58 - change_id: "wc001", 59 - change_id_short: "wc0", 60 - parent_ids: ["b2c3d4e5f6a1"], 61 - parent_edges: [{ parent_id: "b2c3d4e5f6a1", edge_type: "direct" }], 62 - description: "", 63 - author: "alice@example.com", 64 - timestamp: new Date().toISOString(), 65 - is_working_copy: true, 66 - is_immutable: false, 67 - is_mine: true, 68 - is_trunk: false, 69 - bookmarks: [], 70 - }, 71 - { 72 - commit_id: "b2c3d4e5f6a1", 73 - change_id: "feat01", 74 - change_id_short: "fe1", 75 - parent_ids: ["c3d4e5f6a1b2"], 76 - parent_edges: [{ parent_id: "c3d4e5f6a1b2", edge_type: "direct" }], 77 - description: "feat: add user authentication flow", 78 - author: "alice@example.com", 79 - timestamp: new Date(Date.now() - 1800000).toISOString(), 80 - is_working_copy: false, 81 - is_immutable: false, 82 - is_mine: true, 83 - is_trunk: false, 84 - bookmarks: ["feature/auth"], 85 - }, 86 - { 87 - commit_id: "c3d4e5f6a1b2", 88 - change_id: "feat02", 89 - change_id_short: "fe2", 90 - parent_ids: ["d4e5f6a1b2c3"], 91 - parent_edges: [{ parent_id: "d4e5f6a1b2c3", edge_type: "direct" }], 92 - description: "feat: implement login form component", 93 - author: "alice@example.com", 94 - timestamp: new Date(Date.now() - 3600000).toISOString(), 95 - is_working_copy: false, 96 - is_immutable: false, 97 - is_mine: true, 98 - is_trunk: false, 99 - bookmarks: [], 100 - }, 101 - { 102 - commit_id: "d4e5f6a1b2c3", 103 - change_id: "fix001", 104 - change_id_short: "fx1", 105 - parent_ids: ["e5f6a1b2c3d4"], 106 - parent_edges: [{ parent_id: "e5f6a1b2c3d4", edge_type: "direct" }], 107 - description: "fix: resolve race condition in data fetching", 108 - author: "bob@example.com", 109 - timestamp: new Date(Date.now() - 7200000).toISOString(), 110 - is_working_copy: false, 111 - is_immutable: false, 112 - is_mine: true, 113 - is_trunk: false, 114 - bookmarks: [], 115 - }, 116 - { 117 - commit_id: "e5f6a1b2c3d4", 118 - change_id: "refac1", 119 - change_id_short: "rf1", 120 - parent_ids: ["f6a1b2c3d4e5"], 121 - parent_edges: [{ parent_id: "f6a1b2c3d4e5", edge_type: "direct" }], 122 - description: "refactor: extract shared utilities into separate module", 123 - author: "charlie@example.com", 124 - timestamp: new Date(Date.now() - 14400000).toISOString(), 125 - is_working_copy: false, 126 - is_immutable: false, 127 - is_mine: true, 128 - is_trunk: false, 129 - bookmarks: [], 130 - }, 131 - { 132 - commit_id: "f6a1b2c3d4e5", 133 - change_id: "docs01", 134 - change_id_short: "dc1", 135 - parent_ids: ["a1b2c3d4e5f7"], 136 - parent_edges: [{ parent_id: "a1b2c3d4e5f7", edge_type: "direct" }], 137 - description: "docs: update API documentation", 138 - author: "alice@example.com", 139 - timestamp: new Date(Date.now() - 28800000).toISOString(), 140 - is_working_copy: false, 141 - is_immutable: false, 142 - is_mine: true, 143 - is_trunk: false, 144 - bookmarks: [], 145 - }, 146 - { 147 - commit_id: "a1b2c3d4e5f7", 148 - change_id: "merge1", 149 - change_id_short: "mg1", 150 - parent_ids: ["b2c3d4e5f7a1", "x1y2z3a4b5c6"], 151 - parent_edges: [ 152 - { parent_id: "b2c3d4e5f7a1", edge_type: "direct" }, 153 - { parent_id: "x1y2z3a4b5c6", edge_type: "direct" }, 154 - ], 155 - description: "merge: integrate feature branch", 156 - author: "bob@example.com", 157 - timestamp: new Date(Date.now() - 43200000).toISOString(), 158 - is_working_copy: false, 159 - is_immutable: true, 160 - is_mine: false, 161 - is_trunk: true, 162 - bookmarks: ["main"], 163 - }, 164 - { 165 - commit_id: "x1y2z3a4b5c6", 166 - change_id: "side01", 167 - change_id_short: "sd1", 168 - parent_ids: ["b2c3d4e5f7a1"], 169 - parent_edges: [{ parent_id: "b2c3d4e5f7a1", edge_type: "direct" }], 170 - description: "feat: add dark mode support", 171 - author: "charlie@example.com", 172 - timestamp: new Date(Date.now() - 50000000).toISOString(), 173 - is_working_copy: false, 174 - is_immutable: true, 175 - is_mine: false, 176 - is_trunk: false, 177 - bookmarks: [], 178 - }, 179 - { 180 - commit_id: "b2c3d4e5f7a1", 181 - change_id: "init01", 182 - change_id_short: "in1", 183 - parent_ids: ["c3d4e5f7a1b2"], 184 - parent_edges: [{ parent_id: "c3d4e5f7a1b2", edge_type: "direct" }], 185 - description: "feat: initial project setup with build config", 186 - author: "alice@example.com", 187 - timestamp: new Date(Date.now() - 86400000).toISOString(), 188 - is_working_copy: false, 189 - is_immutable: true, 190 - is_mine: false, 191 - is_trunk: false, 192 - bookmarks: [], 193 - }, 194 - { 195 - commit_id: "c3d4e5f7a1b2", 196 - change_id: "root00", 197 - change_id_short: "rt0", 198 - parent_ids: [], 199 - parent_edges: [], 200 - description: "chore: initial commit", 201 - author: "alice@example.com", 202 - timestamp: new Date(Date.now() - 172800000).toISOString(), 203 - is_working_copy: false, 204 - is_immutable: true, 205 - is_mine: false, 206 - is_trunk: false, 207 - bookmarks: [], 208 - }, 209 - ]; 210 - 211 - const handlers: Record<string, (args?: unknown) => unknown> = { 212 - get_projects: () => mockProjects, 213 - upsert_project: (args) => { 214 - const { project } = args as { project: Project }; 215 - const existingIndex = mockProjects.findIndex((p) => p.id === project.id); 216 - if (existingIndex >= 0) { 217 - mockProjects[existingIndex] = project; 218 - } else { 219 - mockProjects = [project, ...mockProjects]; 220 - } 221 - return undefined; 222 - }, 223 - remove_project: (args) => { 224 - const { projectId } = args as { projectId: string }; 225 - mockProjects = mockProjects.filter((p) => p.id !== projectId); 226 - return undefined; 227 - }, 228 - find_project_by_path: (args) => { 229 - const { path } = args as { path: string }; 230 - return mockProjects.find((p) => p.path === path) ?? null; 231 - }, 232 - find_repository: () => "/Users/demo/projects/tatami", 233 - get_revisions: () => mockRevisions, 234 - get_status: (): WorkingCopyStatus => ({ 235 - repo_path: "/Users/demo/projects/tatami", 236 - change_id: "xyz789", 237 - files: [ 238 - { path: "src/main.rs", status: "modified" }, 239 - { path: "README.md", status: "added" }, 240 - ], 241 - }), 242 - get_file_diff: (): string => `--- a/src/main.rs 243 - +++ b/src/main.rs 244 - @@ -1,3 +1,4 @@ 245 - fn main() { 246 - - println!("old"); 247 - + println!("new"); 248 - + println!("extra"); 249 - }`, 250 - get_revision_diff: (): string => `--- a/src/main.rs 251 - +++ b/src/main.rs 252 - @@ -1,3 +1,4 @@ 253 - fn main() { 254 - - println!("old"); 255 - + println!("new"); 256 - + println!("extra"); 257 - } 258 - --- a/README.md 259 - +++ b/README.md 260 - @@ -1,2 +1,3 @@ 261 - # Example Project 262 - +This is a new line 263 - Welcome to the project`, 264 - watch_repository: () => undefined, 265 - unwatch_repository: () => undefined, 266 - }; 267 - 268 - export async function invoke<T>(cmd: string, args?: Record<string, unknown>): Promise<T> { 269 - const handler = handlers[cmd]; 270 - if (!handler) { 271 - throw new Error(`[Mock] No handler for command: ${cmd}`); 272 - } 273 - // Simulate network delay 274 - await new Promise((r) => setTimeout(r, 50)); 275 - return handler(args) as T; 276 - }
-11
apps/desktop/src/mocks/tauri-deep-link.ts
··· 1 - type UnlistenFn = () => void; 2 - 3 - export async function getCurrent(): Promise<string[] | null> { 4 - // In mock mode (browser), there are no deep links on cold start 5 - return null; 6 - } 7 - 8 - export async function onOpenUrl(_handler: (urls: string[]) => void): Promise<UnlistenFn> { 9 - // In mock mode (browser), deep links won't work - just return a no-op unlisten 10 - return () => {}; 11 - }
-11
apps/desktop/src/mocks/tauri-dialog.ts
··· 1 - interface OpenDialogOptions { 2 - directory?: boolean; 3 - multiple?: boolean; 4 - defaultPath?: string; 5 - title?: string; 6 - } 7 - 8 - export async function open(_options?: OpenDialogOptions): Promise<string | null> { 9 - // In mock mode, just return a fake path 10 - return "/Users/demo/projects/tatami"; 11 - }
-16
apps/desktop/src/mocks/tauri-event.ts
··· 1 - type UnlistenFn = () => void; 2 - 3 - interface Event<T> { 4 - payload: T; 5 - } 6 - 7 - type EventCallback<T> = (event: Event<T>) => void; 8 - 9 - export async function listen<T>(_event: string, _handler: EventCallback<T>): Promise<UnlistenFn> { 10 - // In mock mode, never emit events - just return a no-op unlisten 11 - return () => {}; 12 - } 13 - 14 - export async function emit(_event: string, _payload?: unknown): Promise<void> { 15 - // no-op in mock mode 16 - }
-3
apps/desktop/src/mocks/tauri-path.ts
··· 1 - export async function homeDir(): Promise<string> { 2 - return "/Users/demo"; 3 - }
+14
apps/desktop/src/tauri-stub.ts
··· 1 + // This file MUST be imported before any @tauri-apps/* imports 2 + // It sets up a minimal stub so Tauri modules don't crash in browser mode 3 + 4 + const isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window; 5 + 6 + if (!isTauri && typeof window !== "undefined") { 7 + // biome-ignore lint/suspicious/noExplicitAny: Tauri internals stub 8 + (window as any).__TAURI_INTERNALS__ = { 9 + invoke: () => Promise.reject(new Error("Tauri mocks not initialized yet")), 10 + metadata: { currentWindow: { label: "main" }, currentWebview: { label: "main" } }, 11 + }; 12 + } 13 + 14 + export const IS_TAURI = isTauri;
-12
apps/desktop/vite.config.ts
··· 4 4 import tailwindcss from "@tailwindcss/vite"; 5 5 6 6 const host = process.env.TAURI_DEV_HOST; 7 - const isTauri = !!process.env.TAURI_ENV_DEBUG; 8 - 9 - const tauriMocks = isTauri 10 - ? {} 11 - : { 12 - "@tauri-apps/api/core": path.resolve(__dirname, "./src/mocks/tauri-core.ts"), 13 - "@tauri-apps/api/path": path.resolve(__dirname, "./src/mocks/tauri-path.ts"), 14 - "@tauri-apps/api/event": path.resolve(__dirname, "./src/mocks/tauri-event.ts"), 15 - "@tauri-apps/plugin-dialog": path.resolve(__dirname, "./src/mocks/tauri-dialog.ts"), 16 - "@tauri-apps/plugin-deep-link": path.resolve(__dirname, "./src/mocks/tauri-deep-link.ts"), 17 - }; 18 7 19 8 const reactCompilerConfig = {}; 20 9 ··· 30 19 resolve: { 31 20 alias: { 32 21 "@": path.resolve(__dirname, "./src"), 33 - ...tauriMocks, 34 22 }, 35 23 }, 36 24 clearScreen: false,