Skip to content

Commit d487f32

Browse files
committed
feat: add automatic update checker for Tauri desktop app
- Add Rust backend commands: check_for_updates and get_app_version - Implement HTTP version checking against kromacut.com/version.json - Add UpdateChecker React component with dismissible notification - Check for updates on startup and every 4 hours - Add reqwest (HTTP client) and tokio (async runtime) dependencies - Synchronize version to 2.2.0 across package.json and Cargo.toml - Create UPDATE_CHECKER.md with comprehensive documentation - Include example version.json file structure - Update docs with automatic updates feature description
1 parent 0d20ad7 commit d487f32

8 files changed

Lines changed: 279 additions & 136 deletions

File tree

TAURI.md

Lines changed: 30 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,72 @@
11
# Kromacut Native App (Tauri)
22

3-
Kromacut can now be built as a native Mac application using Tauri, offering better performance than the web version.
4-
5-
## Why Tauri?
6-
7-
- **Smaller app size:** 2-3 MB vs 100+ MB with Electron
8-
- **Better performance:** Uses native macOS WebKit instead of bundling Chromium
9-
- **Lower memory usage:** More efficient resource utilization
10-
- **Native integration:** Better macOS integration and feel
3+
Kromacut can be built as a native application for macOS, Windows, and Linux using Tauri.
114

125
## Prerequisites
136

14-
- **Rust:** Required for building native components
7+
- Rust
158
```bash
169
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
1710
source "$HOME/.cargo/env"
1811
```
19-
20-
- **Node.js:** Already required for the web version
12+
- Node.js
2113

2214
## Development
2315

24-
Run the app in development mode:
25-
2616
```bash
2717
npm run tauri:dev
2818
```
2919

30-
This will:
31-
1. Start the Vite dev server on port 5173
32-
2. Launch the native app window
33-
3. Enable hot-reload for fast development
34-
35-
## Building for Production
36-
37-
Build the native Mac app:
20+
## Production Build
3821

3922
```bash
4023
npm run tauri:build
4124
```
4225

43-
This creates two bundles:
44-
1. **Kromacut.app** - Standard macOS application bundle
45-
- Location: `src-tauri/target/release/bundle/macos/Kromacut.app`
46-
- Double-click to run
47-
48-
2. **Kromacut_0.1.0_aarch64.dmg** - DMG installer
49-
- Location: `src-tauri/target/release/bundle/dmg/Kromacut_0.1.0_aarch64.dmg`
50-
- Distributable installer for Apple Silicon Macs
26+
Build artifacts are created under `src-tauri/target/release/bundle/`.
5127

5228
## Configuration
5329

54-
Key Tauri settings in [src-tauri/tauri.conf.json](src-tauri/tauri.conf.json):
55-
56-
- **Window size:** 1400x900 (min: 1000x700) - optimized for the 2-pane layout
57-
- **Bundle identifier:** `com.kromacut.lithophane`
58-
- **Base path:** Automatically switches between `/` (Tauri) and `/Kromacut/` (GitHub Pages)
59-
60-
## Performance Benefits
61-
62-
The native app benefits from:
63-
- **Direct GPU access** for Three.js rendering
64-
- **Native file system** for faster image loading
65-
- **No browser overhead** for better memory management
66-
- **macOS optimization** for M1/M2 chip acceleration
67-
68-
## Web vs Native
69-
70-
Both versions are maintained:
71-
- **Web (GitHub Pages):** `npm run build` → Deploy to https://zeroCoder1.github.io/Kromacut/
72-
- **Native (Tauri):** `npm run tauri:build` → Create Mac app bundle
73-
74-
The codebase is shared; vite.config.ts automatically adapts the base path based on the build target.
75-
76-
## Distribution
77-
78-
### Local Distribution
30+
Main config file: `src-tauri/tauri.conf.json`
7931

80-
To share the app:
81-
1. Use the `.dmg` file from `src-tauri/target/release/bundle/dmg/`
82-
2. Recipients can drag Kromacut.app to their Applications folder
83-
3. **Remove the quarantine attribute** (required for unsigned apps):
84-
```bash
85-
sudo xattr -d com.apple.quarantine /Applications/Kromacut.app
86-
```
87-
4. Launch the app
32+
- Window defaults are set for Kromacut’s two-pane layout.
33+
- Bundle identifier is configured in the same file.
8834

89-
**If users see "Kromacut is damaged" error:**
90-
This happens because the app isn't code-signed. The fix is to remove the quarantine flag that macOS adds to downloaded files:
91-
```bash
92-
sudo xattr -d com.apple.quarantine /Applications/Kromacut.app
93-
```
94-
Enter your password when prompted.
35+
## Versioning and Release
9536

96-
### Automated Releases (GitHub)
37+
When releasing a new version:
9738

98-
The project includes a GitHub Action that automatically builds and releases the Mac app:
39+
1. Update `package.json` version.
40+
2. Update `src-tauri/tauri.conf.json` version.
41+
3. Commit and tag the release.
9942

100-
**To create a new release:**
43+
Example:
10144

10245
```bash
103-
# Update version in both files
104-
# 1. package.json - "version": "0.2.0"
105-
# 2. src-tauri/tauri.conf.json - "version": "0.2.0"
106-
107-
# Commit the changes
10846
git add package.json src-tauri/tauri.conf.json
109-
git commit -m "Bump version to 0.2.0"
110-
111-
# Create and push a version tag
112-
git tag v0.2.0
47+
git commit -m "Bump version to vX.Y.Z"
48+
git tag vX.Y.Z
11349
git push origin main
114-
git push origin v0.2.0
50+
git push origin vX.Y.Z
11551
```
11652

117-
The workflow will automatically:
118-
1. Build for both Apple Silicon (M1/M2/M3) and Intel Macs
119-
2. Create a GitHub release with the tag name
120-
3. Upload both DMG files as release assets
121-
4. Include installation instructions in the release notes
122-
123-
**Manual trigger:**
124-
You can also trigger the workflow manually from the Actions tab on GitHub.
125-
126-
**Release artifacts:**
127-
- `Kromacut_VERSION_aarch64.dmg` - Apple Silicon (M1/M2/M3)
128-
- `Kromacut_VERSION_x86_64.dmg` - Intel Macs
53+
The GitHub Actions workflow will automatically build native applications for:
54+
- **macOS**: Apple Silicon (M1/M2/M3) and Intel
55+
- **Windows**: x64 installer
56+
- **Linux**: AppImage and .deb package
12957

130-
### Code Signing & Notarization (Future Enhancement)
58+
All artifacts are attached to the GitHub release.
13159

132-
Currently, the app is **ad-hoc signed** (configured with `signingIdentity: "-"` in tauri.conf.json). This allows the app to run but users must remove the quarantine attribute after downloading.
60+
## Distribution Notes
13361

134-
**To eliminate the quarantine requirement entirely**, you would need to:
62+
**macOS:** Unsigned builds require removing quarantine:
13563

136-
1. **Enroll in Apple Developer Program** ($99/year)
137-
- Visit: https://developer.apple.com/programs/
138-
139-
2. **Obtain a Developer ID Application certificate**
140-
- Issued through your Apple Developer account
141-
- Allows distribution outside the Mac App Store
142-
143-
3. **Configure Tauri with your signing identity**
144-
```json
145-
"macOS": {
146-
"signingIdentity": "Developer ID Application: Your Name (TEAM_ID)",
147-
"entitlements": "path/to/entitlements.plist"
148-
}
149-
```
150-
151-
4. **Notarize the app with Apple**
152-
- Apple scans the app for malicious content
153-
- Adds a "ticket" that tells Gatekeeper the app is safe
154-
- Required for apps distributed outside the App Store as of macOS 10.15+
155-
156-
**Benefits of notarization:**
157-
- ✅ No quarantine warnings for users
158-
- ✅ No `xattr` command needed
159-
- ✅ Professional distribution
160-
- ✅ Users can simply double-click to install
161-
- ✅ Better trust and user experience
64+
```bash
65+
sudo xattr -d com.apple.quarantine /Applications/Kromacut.app
66+
```
16267

163-
**Current state (v2.1):**
164-
- Ad-hoc signing is enabled
165-
- Users must run: `sudo xattr -d com.apple.quarantine /Applications/Kromacut.app`
166-
- This is acceptable for personal use and small-scale distribution
68+
For notarized distribution, configure a Developer ID signing identity in `tauri.conf.json`.
16769

168-
## Updating
70+
**Windows:** The `.msi` installer may trigger Windows SmartScreen for unsigned builds. Users can click "More info" → "Run anyway".
16971

170-
When the app version changes:
171-
1. Update version in [package.json](package.json)
172-
2. Update version in [src-tauri/tauri.conf.json](src-tauri/tauri.conf.json)
173-
3. Rebuild: `npm run tauri:build`
72+
**Linux:** AppImage bundles are portable and require no installation. `.deb` packages integrate with the system package manager.

UPDATE_CHECKER.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Update Checking System
2+
3+
Kromacut includes an automatic update checker for the Tauri desktop app.
4+
5+
## How It Works
6+
7+
1. **Version Check**: The app periodically checks `https://kromacut.com/version.json` for the latest version.
8+
2. **Comparison**: The fetched version is compared with the installed version.
9+
3. **Notification**: If a newer version is available, a notification appears in the bottom-right corner.
10+
4. **User Action**: Users can download the update or dismiss the notification.
11+
12+
## Version File Format
13+
14+
The `version.json` file should be hosted at `https://kromacut.com/version.json` with the following structure:
15+
16+
```json
17+
{
18+
"version": "2.2.0",
19+
"download_url": "https://github.com/vycdev/Kromacut/releases/latest",
20+
"release_notes": "Bug fixes and performance improvements"
21+
}
22+
```
23+
24+
### Fields
25+
26+
- `version` (required): The latest version number (semver format recommended)
27+
- `download_url` (optional): Direct link to download the update
28+
- `release_notes` (optional): Brief description of what's new
29+
30+
## Update Frequency
31+
32+
- **On Startup**: Checks for updates when the app launches
33+
- **Periodic**: Re-checks every 4 hours while the app is running
34+
- **Non-blocking**: Version checks happen in the background
35+
36+
## Version Synchronization
37+
38+
The version number is managed in multiple places and should be kept in sync:
39+
40+
1. `package.json` - `version` field
41+
2. `src-tauri/tauri.conf.json` - `version` field
42+
3. `src-tauri/Cargo.toml` - `version` field under `[package]`
43+
44+
When releasing a new version, update all three files.
45+
46+
## Disabling Update Checks
47+
48+
Update checks only run in the Tauri desktop environment. The web version is unaffected. To disable update checks in the desktop app, simply don't include the UpdateChecker component.
49+
50+
## Testing
51+
52+
To test the update checker locally:
53+
54+
1. Change the version in `public/version.json` to a higher version
55+
2. Build and run the Tauri app: `npm run tauri:dev`
56+
3. The update notification should appear after a few seconds
57+
58+
## Privacy
59+
60+
The update checker makes a single HTTP GET request to the version endpoint. No user data or telemetry is collected or transmitted.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/version.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"version": "2.2.0",
3+
"download_url": "https://github.com/vycdev/Kromacut/releases/latest",
4+
"release_notes": "Latest release with new features and improvements"
5+
}

src-tauri/Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[package]
22
name = "app"
3-
version = "0.1.0"
4-
description = "A Tauri App"
5-
authors = ["you"]
3+
version = "2.2.0"
4+
description = "Kromacut - Multi-color lithophane 3D print generator"
5+
authors = ["vycdev"]
66
license = ""
77
repository = ""
88
edition = "2021"
@@ -23,3 +23,5 @@ serde = { version = "1.0", features = ["derive"] }
2323
log = "0.4"
2424
tauri = { version = "2.10.0", features = [] }
2525
tauri-plugin-log = "2"
26+
reqwest = { version = "0.12", features = ["json"] }
27+
tokio = { version = "1", features = ["full"] }

src-tauri/src/lib.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,48 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Debug, Serialize, Deserialize)]
4+
struct VersionInfo {
5+
version: String,
6+
download_url: Option<String>,
7+
release_notes: Option<String>,
8+
}
9+
10+
#[tauri::command]
11+
async fn check_for_updates(current_version: String) -> Result<Option<VersionInfo>, String> {
12+
// Try to fetch version info from kromacut.com/version.json
13+
let url = "https://kromacut.com/version.json";
14+
15+
match reqwest::get(url).await {
16+
Ok(response) => {
17+
if response.status().is_success() {
18+
match response.json::<VersionInfo>().await {
19+
Ok(version_info) => {
20+
// Compare versions (simple string comparison for now)
21+
if version_info.version != current_version {
22+
Ok(Some(version_info))
23+
} else {
24+
Ok(None)
25+
}
26+
}
27+
Err(e) => Err(format!("Failed to parse version info: {}", e)),
28+
}
29+
} else {
30+
Err(format!("Server returned status: {}", response.status()))
31+
}
32+
}
33+
Err(e) => Err(format!("Failed to check for updates: {}", e)),
34+
}
35+
}
36+
37+
#[tauri::command]
38+
fn get_app_version() -> String {
39+
env!("CARGO_PKG_VERSION").to_string()
40+
}
41+
142
#[cfg_attr(mobile, tauri::mobile_entry_point)]
243
pub fn run() {
344
tauri::Builder::default()
45+
.invoke_handler(tauri::generate_handler![check_for_updates, get_app_version])
446
.setup(|app| {
547
if cfg!(debug_assertions) {
648
app.handle().plugin(

src/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { useBuildWarning } from './hooks/useBuildWarning';
2727
import ResizableSplitter from './components/ResizableSplitter';
2828
import { ControlsPanel } from './components/ControlsPanel';
2929
import { usePaletteManager } from './hooks/usePaletteManager';
30+
import { UpdateChecker } from './components/UpdateChecker';
3031
import {
3132
AlertDialog,
3233
AlertDialogContent,
@@ -587,6 +588,9 @@ function App(): React.ReactElement | null {
587588
</AlertDialogFooter>
588589
</AlertDialogContent>
589590
</AlertDialog>
591+
592+
{/* Update checker for Tauri desktop app */}
593+
<UpdateChecker />
590594
</div>
591595
);
592596
}

0 commit comments

Comments
 (0)