Aller au contenu
CADCAMFUN
Docs

Documentation

Interface utilisateur de bureau

Des espaces de travail SolidJS, un client API local et un shell Tauri possédant une intégration native.

Traduit automatiquement de l'anglais. Voir l'original en anglais

Architecture des applications

L'application de bureau combine une vue Web SolidJS, Vite, Three.js et un shell Tauri v2 Rust. La vue Web possède les écrans et l'état d'interaction. Le sidecar Bun possède des gestionnaires d'API, un accès aux bases de données, des sessions d'IA et des services de projet. Le processus Rust est propriétaire de la fenêtre, des menus, de la barre d'état système, des boîtes de dialogue du système d'exploitation, de l'accès au trousseau, des mises à jour et du cycle de vie du sidecar.

apps/desktop/src/main.tsx monte l'application. app/App.tsx établit la connexion API et fournit l'état partagé ; app/routes.tsx mappe les URL vers des modules de page paresseux. Les écrans de fonctionnalités sont en direct features/. La présence d'une route n'établit pas la disponibilité de ses services externes : la facturation nécessite une configuration Stripe et l'IA a besoin d'un fournisseur configuré.

Démarrage et récupération de connexion

  1. Le shell démarre le sidecar fourni avec un jeton de lancement généré et des répertoires de données d'application et de migration.
  2. Le sidecar lie un port éphémère sur 127.0.0.1, attend que sa route de santé réponde et écrit un JSON ready événement contenant le port.
  3. La vue Web invoque get_sidecar_endpoint et crée un client API et un runtime Effect géré.
  4. Une demande d’intégrité réussie crée un état d’application et monte le routeur et le shell.

La vue Web autorise 150 secondes pour la récupération de la connexion, avec un délai d'expiration de 30 secondes par tentative et une pause entre les tentatives de 750 millisecondes. Les tentatives infructueuses suppriment le point de terminaison mis en cache afin qu’un sidecar redémarré puisse fournir un nouveau port. Le superviseur Rust attend 60 secondes pour chaque poignée de main prête et autorise un redémarrage automatique. La nouvelle tentative devient disponible lorsque le budget de connexion WebView expire.

L'aperçu du navigateur utilise une API en mémoire

En dehors de Tauri, un navigateur sans VITE_SIDECAR_URL utilise src/testing/fake-api.ts. Les données d'aperçu sont locales à la page en cours d'exécution ; les collections non prises en charge renvoient HTTP 501. Pour connecter un navigateur à un véritable sidecar, fournissez les deux VITE_SIDECAR_URL et VITE_SIDECAR_TOKEN au démarrage de Vite.

Itinéraires à l'écran

ZoneItinéraires et modules
Projets/projects, /projects/create, /projects/:id, et /projects/:id/history; écrans dans features/projects/screens.
Conception et fabrication/cad monte CadPage; /cam monte CamPage. Les dessins et parcours d'outils enregistrés ont des itinéraires de détail distincts.
Ressources/library, /materials, /tools, /machine, et leurs pages de détails utilisent des modules de fonctionnalités de bibliothèque. Les composants ont des itinéraires de liste et de détail.
Assistant/ai et le panneau assistant ancré partage l'état de la fonctionnalité AI. L'activité IA fait basculer le panneau.
Paramètres/settings, /settings/companion, les paramètres MCP et les paramètres d'abonnement.
Compte et collaborationL'authentification, le profil, l'organisation, l'invitation, le chat, le marché, le plugin, les coûts, les analyses et l'administration acheminent chaque module de fonctionnalité de chargement.

Utiliser app/routes.tsx pour les noms exacts des paramètres et pages/ pour localiser l'écran monté sur une URL. Les adaptateurs de route sont intentionnellement petits ; lisez l'écran et ses appels API lors du diagnostic d'une vue vide ou d'une action ayant échoué.

Organisation source

  • app/: démarrage, routeur, client API global, intégration native, shell et raccourcis clavier.
  • pages/: adaptateurs de routage important ou réexportant des écrans.
  • features/: zones de produits avec écrans, composants, hooks, état et aides spécifiques au domaine.
  • shared/: contrôles réutilisables, composants shell, état de l'application, mise en cache des requêtes et historique des commandes.
  • viewport/: dessin sur toile, accrochage, gestes d'outils, rendu Three.js, maillage et lecture.
  • i18n/, styles/, et testing/: traductions, styles globaux et montages de test.

Le bureau dépend de @cadcamfun/api pour le contrat HTTP et sur @cadcamfun/core pour les opérations de géométrie et de FAO. La persistance de la base de données reste derrière l'API sidecar. L'historique de l'éditeur local est distinct des versions persistantes de dessin ou de parcours d'outil et du contrôle de version du projet.

Coquille native

La fenêtre de production est de 1440 × 900 par défaut, avec un minimum de 960 × 600. Tauri met en scène le frontend à partir de apps/desktop/dist, un sidecar spécifique à une cible de src-tauri/binaries, et généré des migrations en tant que ressources. Il enregistre .cadcam, .nc, et .gcode associations de fichiers. L'ouverture d'un fichier pris en charge ou le lancement d'une deuxième instance transfère les chemins de fichiers vers la fenêtre existante.

src-tauri/src/sidecar.rs supervise le processus de l'enfant. La fermeture de l'application écrit un {"event":"shutdown"} faites la queue devant le stdin de l'enfant et attendez brièvement avant de le récolter ; l'enfant observe également la fermeture du stdin. Le jeton de lancement est constitué de 32 octets aléatoires, codés en hexadécimal sous forme de 64 caractères, et les lignes de journal sidecar pouvant contenir des informations d'identification sont rédigées. Les journaux sont séparés de la sortie standard, qui transporte la poignée de main prêt/erreur. Les secrets natifs sont accessibles via src-tauri/src/secrets.rs à l’aide du trousseau du système d’exploitation.

Sur macOS, le shell enregistre le plugin Liquid Glass. La vue Web suit le réglage du verre et revient lorsque l'effet n'est pas disponible. La configuration de l'App Store désactive l'option API privée ; la configuration régulière le permet. Ce sont des configurations de construction distinctes.

Limites de sécurité et de persistance

La politique de contenu de production autorise les ressources locales, les connexions API de bouclage, les images de données/blob et l'évaluation WebAssembly. Il n'autorise pas l'exécution arbitraire de scripts à distance. Les autorisations natives sont limitées à src-tauri/capabilities; la politique de développement autorise également Vite et son websocket.

open_path canonise les chemins, les limite aux répertoires utilisateur/application autorisés et rejette les extensions exécutables telles que .exe, .app, .sh, .bat, .msi, et .jar. .. les segments et les liens symboliques ne peuvent pas échapper aux dossiers autorisés car les deux côtés sont canonisés. La sélection et l'enregistrement des fichiers utilisent des boîtes de dialogue et une validation natives. Un jeton de lancement donne accès à l'API de l'application locale ; traitez-le séparément d'un jeton compagnon ou d'un jeton de pont AI à l'échelle du projet.

Les paramètres de l'interface utilisateur, l'état des requêtes API, les commandes de l'éditeur, les versions de projet stockées et les secrets natifs ont des propriétaires différents. Diagnostiquez chacun via son service réel plutôt que de supposer que tous les états des applications sont stockés dans SQLite.

Intégration des fonctionnalités

Les modules de fonctionnalités CAO et CAM composent des composants de fenêtre d'affichage réutilisables avec leurs propres panneaux, magasins et flux de sauvegarde. Le panneau d'assistant reçoit le contexte du projet et de l'éditeur et diffuse les événements des outils via l'état des fonctionnalités de l'IA. Les écrans de ressources utilisent le client API au lieu d'accéder directement à la base de données.

Pour une modification de l'interface utilisateur, suivez l'adaptateur d'itinéraire jusqu'à son écran de fonctionnalités, puis inspectez le magasin de fonctionnalités ou le hook qui envoie la demande. Réutilisez les composants partagés uniquement lorsque leur contrat existant correspond à l'interaction. Conservez la géométrie pure dans le package de base et le comportement natif du système d’exploitation dans le shell Rust.

Chargement de l'itinéraire et erreurs

Chaque itinéraire utilise la limite d'importation paresseuse de Solid. Le tableau comprend une page fourre-tout, /500, /offline, et les voies légales. Une navigation directe dans le navigateur doit être assurée via le serveur de développement Vite ou la vue Web fournie afin que le routeur client puisse résoudre l'URL.

L'API d'aperçu implémente un ensemble limité de collections et peut délibérément injecter des échecs de requêtes dans les tests. Un rendu d'aperçu réussi démontre le comportement de l'interface utilisateur par rapport à ces appareils ; vérifiez la persistance, les autorisations, le streaming et les intégrations externes avec le sidecar en direct.

Interface de commande native

CommandeBut
get_sidecar_endpointAttendez le sidecar supervisé et renvoyez son URL de base et son jeton de lancement. L'attente couvre un redémarrage : deux délais d'attente de préparation de 60 secondes plus 5 secondes (125 secondes).
get_logs_dir, open_pathRésolvez le répertoire du journal des applications sous forme de chaîne et ouvrez un chemin absolu existant avec l'ouvreur du système d'exploitation. Les chemins doivent être résolus dans le dossier Données de l'application, Journal, Documents, Téléchargements ou Bureau.
secret_get, secret_set, secret_deleteAccédez aux entrées du trousseau natif sous le com.cadcamfun.app service. Les clés sont constituées de 1–128 octets de lettres ASCII, de chiffres et . _ - : (par exemple ai.anthropic.apiKey); secret_get retours null pour une entrée manquante.
pick_file, save_filepick_file({ filters: [{ name, extensions }] }) renvoie le chemin choisi ou null en cas d'annulation. save_file({ defaultName, contents }) écrit du texte UTF-8 sur le chemin choisi et le renvoie, ou null en cas d'annulation ; les répertoires et les extensions exécutables sont rejetés.
set_recent_projectsActualisez le menu des projets récents de la barre d'état.
check_for_updates, install_updateDemandez une vérification du programme de mise à jour ou installez une mise à jour en attente. install_update accepte une option unsavedWork drapeau (par défaut false) afin qu'une installation n'interrompe pas un éditeur ouvert.

The invoke handler is registered in src-tauri/src/lib.rs. Capabilities and generated command permissions also control availability; command registration alone does not establish webview access. Command errors are serialized as { kind, message } with kinds such as sidecar, invalid_path, io, dialog, and path; no command panics.

Événements autochtones

La coquille émet sidecar-status pour les changements de cycle de vie, open-file avec des chemins pris en charge, menu pour la sélection du menu, et update://status pour la progression du programme de mise à jour. Les sélections de projets récents dans le bac sont représentées par tray.recent.<projectId> identifiants de menu. Les modules de menu et de plateau du shell définissent leurs ensembles complets d'identifiants.

Les écouteurs doivent être limités au cycle de vie de leur composant ou de leur application et supprimés lors du nettoyage. La vue Web doit résoudre à nouveau le point de terminaison après un redémarrage du sidecar plutôt que de continuer à utiliser le port précédent.

Développement et vérification

Exécuter à partir de la racine du référentiel
bun run --filter @cadcamfun/desktop dev
bun run desktop:dev
bun run --filter @cadcamfun/desktop typecheck
bun test apps/desktop/src
bun run build:desktop

La première commande exécute un aperçu du navigateur. desktop:dev compile le véritable sidecar et effectue les migrations avant de démarrer Tauri. Le package de bureau tauri:dev le script crée à la place un binaire stub uniquement lorsqu'aucun binaire n'existe ; utilisez-le pour un travail de shell isolé et vérifiez quel binaire est présent avant d'interpréter ses réponses API.

Le bureau build le script s'exécute vite build seulement; il ne compile pas le sidecar ni ne regroupe un bundle Tauri. Utiliser bun scripts/build.ts pour le pipeline de versions complètes (voir Libérer).

Préférences et paramètres

Le magasin de paramètres partagés conserve un enregistrement validé sous cadcamfun.settings dans le stockage local de la vue Web. Les champs manquants, invalides ou illisibles s'affichent indépendamment. Une zone de stockage pleine ou bloquée n'arrête pas l'édition, mais les modifications de préférences peuvent ne pas persister. Les préférences d'aperçu du navigateur appartiennent à l'origine du navigateur et sont distinctes des préférences d'affichage Web natives.

ParamètreValeurs acceptées/par défautEffet opérationnel
Thèmelight, dark, system; système par défautLe mode système suit les modifications de la palette de couleurs du système d'exploitation.
Unités d'affichagemm ou in; par défaut mmPrésentation des contrôles ; les coordonnées du dessin de base restent en millimètres.
DécimalesEntier 0–6 ; par défaut 3Précision de présentation de la longueur.
Message par défautgrbl, linuxcnc, smoothwb, gcode, fanuc; grbl par défautUne grammaire de sortie sélectionnée est une préférence et non une preuve que la machine est configurée ou vérifiée.
Tolérance de dessinTolérance de base validée ; par défaut 0.01 mmPréférence de précision partagée utilisée par les consommateurs de dessin/parcours d'outil.
État d'accrochagebooléen ; activé par défautPréférence de statut partagé. Les éditeurs individuels sont propriétaires de leur comportement de capture ; le autonome Editor2D active actuellement son accrochage à la grille en interne.
Verrebooléen ; activé par défautDemande du matériel de fenêtre macOS lorsque l'hôte natif le prend en charge.

L'écran Paramètres comporte les onglets Profil, Compte, Sécurité, Abonnement, Notifications, IA, Appareils et Langue. L'onglet Appareils intègre le panneau de passerelle compagnon. Les paramètres de langue incluent la bascule en verre. Le magasin de paramètres régionaux communs valide actuellement les paramètres régionaux par défaut ; ne déduisez pas de couverture de traduction supplémentaire à partir d’une liste d’étiquettes d’affichage.

Enregistrer et rouvrir un programme CAM

  1. Générez ou chargez du code NC dans CAM et ouvrez la boîte de dialogue de sauvegarde/exportation à partir de son point d'entrée existant.
  2. Pour une exportation de fichier, choisissez G-code ou le format de parcours d'outil portable. G-code télécharge le texte NC actuel ; le choix du parcours d'outil écrit un .cam.json instantané.
  3. Pour la persistance de l'application, choisissez un projet existant, un nouveau projet ou mettez à jour le programme déjà enregistré. Fournissez le nom du programme et les champs de destination requis.
  4. Lors de la mise à jour, le flux de sauvegarde enregistre le programme complet précédent en tant que version du parcours d'outil avant de remplacer les données actuelles.
  5. Ouvrez l'élément enregistré sur son itinéraire de détail de parcours d'outil pour inspecter ou restaurer les versions.

Le résumé de sauvegarde comprend les lignes CN, les octets, les mouvements, les identifiants d'outils, les noms d'opérations, le brut, les unités, le décalage d'origine et l'identité de vérification lorsque cette preuve appartient à la CN actuelle. Un texte NC modifié peut rendre obsolètes des preuves précédemment calculées. Passez en revue la relation code/preuve actuelle avant de vous fier au résumé.

Si la création d'un nouveau projet réussit mais qu'une étape de sauvegarde ultérieure échoue, le modal conserve la destination créée pour les nouvelles tentatives et inclut son identifiant dans l'erreur. Réessayer dans ce modal évite de créer à nouveau le même projet. Ne présumez pas que le flux de sauvegarde est une transaction atomique entre ressources.

L'exportation de fichiers et la persistance du projet sont des opérations différentes

Un fichier G-code téléchargé ne crée pas de ligne de parcours d'outil de projet. Un instantané portable contient un état plus riche qu'un simple NC. Vérifiez un programme enregistré en le rouvrant depuis l'application et vérifiez une exportation en inspectant le fichier téléchargé.

Diagnostic du clavier et des pannes

Cmd/Ctrl+K ouvre la palette de commandes et Cmd/Ctrl+J fait basculer le panneau assistant. Les raccourcis du shell sont ignorés lorsque le focus se trouve sur un élément d'entrée, de zone de texte, de sélection ou de contenu modifiable. Les canevas de l'éditeur ont leur propre gestion du clavier. Plusieurs rappels de commandes shell, notamment Enregistrer/Exporter dans la table de raccourcis générique, sont des espaces réservés ; utilisez les contrôles de sauvegarde/exportation réels de la fonctionnalité au lieu de supposer que chaque accélérateur répertorié effectue une opération sur le document.

Comportement observéVérifier
Le démarrage attend, puis Réessayer apparaîtErreur sidecar/sortie prête, binaire cible, ressource de migration et journaux d'application. Un port mis en cache peut appartenir à un processus antérieur.
Un écran s'affiche mais demande le retour 501Mode appareil du navigateur. Démarrez le vrai sidecar et transmettez les deux variables de point de terminaison Vite.
Les données de bureau diffèrent d'un script manuelLe répertoire de données et le jeton de chaque processus ; un nom de fichier à lui seul n'identifie pas la base de données.
Une commande native n'est pas disponibleInvoquez l’enregistrement, les autorisations de fonctionnalités, la prise en charge du système d’exploitation et si le code s’exécute dans Tauri.
Les paramètres sont rétablis après la relanceDisponibilité et validation du stockage. Les champs stockés non valides reviennent aux valeurs par défaut.
La preuve du programme enregistré diffère de NCSi NC a été modifié après la génération. Recalculez la vérification appropriée pour le texte/programme réel.

Ancres de mise en œuvre : shared/state/settings.ts, app/shortcuts.ts, features/settings/screens/settings.tsx, et features/cam/components/SaveCamModal.tsx.

Charges utiles d'événements natifs

ÉvénementCharge utileRemarques
sidecar-status{ state: "starting" }, { state: "ready", port }, { state: "restarting" }, { state: "failed", message }Après restarting, appel get_sidecar_endpoint encore; le port change.
update://statusstatus: checking, upToDate (version), available (version, notes, date, critical), downloading (downloaded, total), ready (version), failed (message); plus dismissibleUne mise à jour critique et un redémarrage en attente ne sont pas écartables. Un échec de vérification n’est jamais affiché comme une erreur bloquante.
menuID d'élément de menu, tel que file.new, file.open, file.save, view.devtools, help.documentationUtilisation des articles du plateau tray.quit et tray.recent.<projectId>.
open-fileChemins de .cadcam, .nc, ou .gcode fichiersEnvoyé lorsque le système d'exploitation ouvre un fichier avec l'application ou qu'une deuxième instance est lancée.
install_update peut être refusé avec un motif tapé : unsavedWork ("l'éditeur a du travail non enregistré ; appliquez la mise à jour une fois enregistrée"), noneAvailable (rien en attente, ou déjà installé), ou failed (le téléchargement ou la vérification de la signature a échoué). Il installe uniquement la mise à jour annoncée par la dernière vérification.
Appel de commandes natives depuis la vue Web
import { invoke } from "@tauri-apps/api/core"
import { listen } from "@tauri-apps/api/event"

const { baseUrl, token } = await invoke<{ baseUrl: string; token: string }>("get_sidecar_endpoint")

const path = await invoke<string | null>("pick_file", {
  filters: [{ name: "G-code", extensions: ["nc", "gcode"] }],
})                                    // null when the user cancels

await invoke("save_file", { defaultName: "part.nc", contents: gcodeText })

const unlisten = await listen<{ state: string; port?: number }>("sidecar-status", (e) => {
  if (e.payload.state === "ready") reconnect()
})
// later: unlisten()

try {
  await invoke("install_update", { unsavedWork: editorIsDirty })
} catch (error) {
  // { kind, message }: the update variant carries the refusal (unsavedWork | noneAvailable | failed)
}

get_sidecar_endpoint retours { baseUrl, token } (sérialisé dans camelCase à partir de SidecarEndpoint). Les erreurs de chaque commande arrivent sous forme de valeur rejetée de invoke, en forme { kind, message }.

Raccourcis clavier

RaccourciActionGroupe
Cmd/Ctrl+KOuvrir la palette de commandesnavigation
Cmd/Ctrl+Shift+PNouveau projetnavigation
Cmd/Ctrl+Z / Cmd/Ctrl+Shift+ZAnnuler/rétablirmodifier
Cmd/Ctrl+S, Cmd/Ctrl+Shift+EEnregistrer, exporter (espaces réservés du shell ; utiliser les propres contrôles de la fonctionnalité)modifier
Cmd/Ctrl+0Zoomer pour s'adaptervoir
Cmd/Ctrl+= / Cmd/Ctrl+-Zoom avant/arrièrevoir
Cmd/Ctrl+JBasculer le panneau Assistantai
Cmd s'applique sur macOS et Ctrl autre part. L'ID de chaque raccourci est également son suffixe de clé de traduction (par exemple settings.shortcut.palette), et l'écran Paramètres affiche ce même tableau, de sorte que la documentation et l'application ne peuvent pas se séparer.

Chaque itinéraire d'écran

Le routeur dans apps/desktop/src/app/routes.tsx déclare 68 routes, chacune chargée paresseusement depuis apps/desktop/src/pages/ (les segments dynamiques sont _id_.tsx fichiers). Regroupés par premier segment :

ZoneItinéraires
**
500/500
admin/admin/analytics /admin/feature-flags
ai/ai
analytics/analytics/history /analytics
auth/auth/forgot-password /auth/magic-link /auth/magic-link/verify /auth/reset-password /auth/signin /auth/signup /auth/two-factor /auth/verify-email /auth/verify
cad/cad
cam/cam
costs/costs
components/components/:id /components
drawings/drawings/:id
//
invitations/invitations/:token
legal/legal/privacy /legal/terms /legal/third-party-licenses
library/library
machine/machine/:id /machine
marketplace/marketplace /marketplace/items/:id /marketplace/purchase/success /marketplace/purchases /marketplace/seller/dashboard
materials/materials/:id /materials
mcp/mcp/directory /mcp/servers/:id
offline/offline
organizations/organizations/:id /organizations/:id/chat/:conversationId /organizations/:id/chat /organizations/:id/chat/new-group /organizations/:id/chat/new /organizations/create /organizations
plugins/plugins/:id /plugins
pricing/pricing
profile/profile /profile/settings
projects/projects/:id/history /projects/:id /projects/create /projects
settings/settings /settings/companion /settings/mcp/config-editor /settings/mcp/edit/:id /settings/mcp /settings/subscription
third-party-licenses/third-party-licenses
toolpaths/toolpaths/:id /toolpaths
tools/tools/:id /tools
waitlist/waitlist
* affiche la page 404 et /500 la page d'erreur. /offline restitue l'écran hors ligne ; comme les pages d'authentification, d'invitation, 404, 500 et de réussite d'achat, il utilise la mise en page autonome sans le chrome de l'application. Étant donné que chaque page est une importation paresseuse, le code d'un écran n'est chargé que lors de la première visite ; un échec de chargement de bloc apparaît comme une erreur d'itinéraire, et non comme une application vide.

En 3D

Topologie des processus de bureau Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
Processes at run time. The Tauri shell spawns the sidecar and waits for its {”event”:”ready”,”port”:N} line on stdout (sidecar.rs); the webview then talks HTTP to 127.0.0.1 on that port with the bearer token. The sidecar owns the SQLite database, the embedded nikcli AI host (CADCAMFUN_AI_HOST=nikcli, the default) and plugins; the mobile app reaches it through companion pairing.