diff --git a/.gitignore b/.gitignore index 89102c0..10e5554 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ node_modules/ dist/ *.tsbuildinfo +# Rust / Cargo +target/ + # Turborepo .turbo/ diff --git a/apps/desktop/package.json b/apps/desktop/package.json new file mode 100644 index 0000000..1a96b96 --- /dev/null +++ b/apps/desktop/package.json @@ -0,0 +1,17 @@ +{ + "name": "@tessera/desktop", + "version": "0.0.1", + "private": true, + "scripts": { + "tauri": "tauri", + "dev": "tauri dev", + "build": "tauri build" + }, + "dependencies": { + "@tauri-apps/api": "^2.11.1", + "@tauri-apps/plugin-store": "^2.4.3" + }, + "devDependencies": { + "@tauri-apps/cli": "^2.11.3" + } +} diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml new file mode 100644 index 0000000..fc99fad --- /dev/null +++ b/apps/desktop/src-tauri/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "tessera-desktop" +version = "0.0.1" +edition = "2021" + +[lib] +name = "tessera_desktop_lib" +crate-type = ["cdylib", "staticlib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +tauri = { version = "2", features = ["tray-icon"] } +tauri-plugin-store = "2" +serde = { version = "1", features = ["derive"] } +serde_json = "1" diff --git a/apps/desktop/src-tauri/build.rs b/apps/desktop/src-tauri/build.rs new file mode 100644 index 0000000..d860e1e --- /dev/null +++ b/apps/desktop/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json new file mode 100644 index 0000000..34e0cab --- /dev/null +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -0,0 +1,10 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "Tessera desktop capabilities", + "windows": ["main"], + "permissions": [ + "core:default", + "store:default" + ] +} diff --git a/apps/desktop/src-tauri/icons/128x128.png b/apps/desktop/src-tauri/icons/128x128.png new file mode 100644 index 0000000..d1fd469 Binary files /dev/null and b/apps/desktop/src-tauri/icons/128x128.png differ diff --git a/apps/desktop/src-tauri/icons/icon.ico b/apps/desktop/src-tauri/icons/icon.ico new file mode 100644 index 0000000..5b17153 Binary files /dev/null and b/apps/desktop/src-tauri/icons/icon.ico differ diff --git a/apps/desktop/src-tauri/icons/icon.png b/apps/desktop/src-tauri/icons/icon.png new file mode 100644 index 0000000..04d4537 Binary files /dev/null and b/apps/desktop/src-tauri/icons/icon.png differ diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs new file mode 100644 index 0000000..17a535f --- /dev/null +++ b/apps/desktop/src-tauri/src/lib.rs @@ -0,0 +1,36 @@ +use tauri::Manager; +use tauri_plugin_store::StoreExt; + +/// Main entry point for the Tessera desktop application. +/// +/// Registers plugins, checks for a stored server URL on startup, +/// and either navigates to the configured server or shows the +/// bundled setup page for first-run configuration. +pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_store::Builder::new().build()) + .setup(|app| { + // Attempt to read a previously stored server URL + let store = app.store("config.json")?; + let server_url = store.get("server_url"); + + if let Some(url_value) = server_url { + if let Some(url_str) = url_value.as_str() { + if !url_str.is_empty() { + // Navigate the main window to the configured server URL + if let Some(window) = app.get_webview_window("main") { + if let Ok(parsed) = url_str.parse::() { + let _ = window.navigate(parsed); + } + } + } + } + } + // If no server_url is stored, the WebView remains on the + // bundled setup page (frontendDist = ../src/setup.html) + + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running Tessera desktop application"); +} diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs new file mode 100644 index 0000000..9b8afb9 --- /dev/null +++ b/apps/desktop/src-tauri/src/main.rs @@ -0,0 +1,6 @@ +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + tessera_desktop_lib::run() +} diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json new file mode 100644 index 0000000..9211c9b --- /dev/null +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json", + "productName": "Tessera", + "version": "0.0.1", + "identifier": "de.ctl.tessera.desktop", + "build": { + "frontendDist": "../src", + "devUrl": "http://localhost:1420" + }, + "app": { + "withGlobalTauri": true, + "windows": [ + { + "label": "main", + "title": "Tessera", + "width": 1280, + "height": 800, + "center": true, + "decorations": true, + "resizable": true + } + ], + "security": { + "csp": "default-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src *; img-src * data:; font-src * data:; style-src 'self' 'unsafe-inline' *; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://unpkg.com" + } + }, + "bundle": { + "active": true, + "targets": ["appimage", "nsis"], + "icon": ["icons/icon.png", "icons/icon.ico"] + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e262a3d..6e7f37d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,6 +127,19 @@ importers: specifier: ^5.5.0 version: 5.9.3 + apps/desktop: + dependencies: + '@tauri-apps/api': + specifier: ^2.11.1 + version: 2.11.1 + '@tauri-apps/plugin-store': + specifier: ^2.4.3 + version: 2.4.3 + devDependencies: + '@tauri-apps/cli': + specifier: ^2.11.3 + version: 2.11.3 + apps/web: dependencies: '@uiw/react-md-editor': @@ -1431,6 +1444,83 @@ packages: '@tailwindcss/postcss@4.3.1': resolution: {integrity: sha512-dNJuNbdEJT/SWRuXTYP1WSamelsz3ztkUsdtWQPjrexysrTpaEPM40P/71knXiXLYEojqPOEGitVLLpPMS5T6A==} + '@tauri-apps/api@2.11.1': + resolution: {integrity: sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==} + + '@tauri-apps/cli-darwin-arm64@2.11.3': + resolution: {integrity: sha512-BxpaM8bsCoXs3wd4WKYhas/G1gs7+r7B+e4WnyRk2GEoVOouJB1hoL6E6YLXZDXbYci6VFdrNnobQwd2uVL4ew==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tauri-apps/cli-darwin-x64@2.11.3': + resolution: {integrity: sha512-DbZYuPB1ZEzcAHYeyCvo3ltzM27+aXwPloCrtexPnmgPgulYJm3TOq6aC4S+wPhSXteddg8zImtNkvx/gQzmwg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tauri-apps/cli-linux-arm-gnueabihf@2.11.3': + resolution: {integrity: sha512-741NduqBmz1XkdU8yz3OI/kBZtqHbvxo9F9ytIeWYU69/Ba9dcZEbqOU++Dp0G/XU8vAI0TfTywEl+p+BbLvaA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tauri-apps/cli-linux-arm64-gnu@2.11.3': + resolution: {integrity: sha512-RWAXT8pTqIczXcoic+LXlo6uEbAXGB0cgh6Pg7Y9xVnEbzryQ1JHtRGj9SxzrKSemBIDBH6Qc24kK2G69i8ofA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tauri-apps/cli-linux-arm64-musl@2.11.3': + resolution: {integrity: sha512-qomqYS+yAkd0gXMRmhguWXc7RfVN+XKKXaEwbf5QmKURwydLFOTldd6F8/WoZDSsBMrV8dpNxz0YneGLmobiSA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tauri-apps/cli-linux-riscv64-gnu@2.11.3': + resolution: {integrity: sha512-jOCXbDqeDj5XcclsOBAaXjtTgwZCVg8zEZ+dbPUCoADOgljFgL0rOkYTc96vUYgOrYEfuHYihWMxIDGaD6GwJw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + + '@tauri-apps/cli-linux-x64-gnu@2.11.3': + resolution: {integrity: sha512-+u3HO/F3gHwL48t9gWN/urqZvpaEJzBFmTaq5eSIhvy8TOvnhb+LgJr3Q3BG+5JxuBrCUjqtOEz6gMttdJFSBA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tauri-apps/cli-linux-x64-musl@2.11.3': + resolution: {integrity: sha512-spr5Jpr6KF/vehkLwJ0YmdGv8QwpWU+uw7J8bgijO0sox6ZCYsSNMbcsQjTqPi4xl+p0woIYpWXgChgHYpAc8g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tauri-apps/cli-win32-arm64-msvc@2.11.3': + resolution: {integrity: sha512-abkoRQih5xBa3vz2spWaex0kP/MzVzVPQHom2f8jnCq46R/luOD6Uy85EMU9/bfzf6ZzdorWJsgO+OMX90Fx2w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tauri-apps/cli-win32-ia32-msvc@2.11.3': + resolution: {integrity: sha512-Vy6AvzFm1G40hg3r+OYDB3jkuu7R4wnMzbQBKuun9v6Cgg8IierpLL7toMzrZKs/8NlG8Sg4x1iLFR52oknyHg==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@tauri-apps/cli-win32-x64-msvc@2.11.3': + resolution: {integrity: sha512-GlciF75GdbseajOyib2aCHwE3BXIqZ1liGKWLFRvCdN5wm8h8hFssEVKQ/6E+2jsMLg9v7LCTb983YFnn0QSww==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tauri-apps/cli@2.11.3': + resolution: {integrity: sha512-EElQe8z8uD7Pi5++tJ/UfEwWuK08rd3oCDYdeIbJAb6pZRrxlqmoF5gh5H5YvzmUPhS4IRCaLSsQhvWkrfK+GQ==} + engines: {node: '>= 10'} + hasBin: true + + '@tauri-apps/plugin-store@2.4.3': + resolution: {integrity: sha512-9LWPj9yMphRi9czEtUv87XHbl1b6xgd9EXpPrUnq6nG7+nbtoF84d4Kwz9xhAv/Hf30sr58pq7EOlyI936y8qw==} + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -6089,6 +6179,59 @@ snapshots: postcss: 8.5.15 tailwindcss: 4.3.1 + '@tauri-apps/api@2.11.1': {} + + '@tauri-apps/cli-darwin-arm64@2.11.3': + optional: true + + '@tauri-apps/cli-darwin-x64@2.11.3': + optional: true + + '@tauri-apps/cli-linux-arm-gnueabihf@2.11.3': + optional: true + + '@tauri-apps/cli-linux-arm64-gnu@2.11.3': + optional: true + + '@tauri-apps/cli-linux-arm64-musl@2.11.3': + optional: true + + '@tauri-apps/cli-linux-riscv64-gnu@2.11.3': + optional: true + + '@tauri-apps/cli-linux-x64-gnu@2.11.3': + optional: true + + '@tauri-apps/cli-linux-x64-musl@2.11.3': + optional: true + + '@tauri-apps/cli-win32-arm64-msvc@2.11.3': + optional: true + + '@tauri-apps/cli-win32-ia32-msvc@2.11.3': + optional: true + + '@tauri-apps/cli-win32-x64-msvc@2.11.3': + optional: true + + '@tauri-apps/cli@2.11.3': + optionalDependencies: + '@tauri-apps/cli-darwin-arm64': 2.11.3 + '@tauri-apps/cli-darwin-x64': 2.11.3 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.11.3 + '@tauri-apps/cli-linux-arm64-gnu': 2.11.3 + '@tauri-apps/cli-linux-arm64-musl': 2.11.3 + '@tauri-apps/cli-linux-riscv64-gnu': 2.11.3 + '@tauri-apps/cli-linux-x64-gnu': 2.11.3 + '@tauri-apps/cli-linux-x64-musl': 2.11.3 + '@tauri-apps/cli-win32-arm64-msvc': 2.11.3 + '@tauri-apps/cli-win32-ia32-msvc': 2.11.3 + '@tauri-apps/cli-win32-x64-msvc': 2.11.3 + + '@tauri-apps/plugin-store@2.4.3': + dependencies: + '@tauri-apps/api': 2.11.1 + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.7