Skip to content

Commit 9905334

Browse files
committed
feat: notification
1 parent c983614 commit 9905334

File tree

6 files changed

+190
-27
lines changed

6 files changed

+190
-27
lines changed

README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,7 @@ Your Tauri signing key is located at `~/.tauri/milo.key`. **CRITICAL:** Back thi
9191

9292
### 🚀 Release Process
9393

94-
```bash
95-
# Export signing key
96-
export TAURI_SIGNING_PRIVATE_KEY=$(cat ~/.tauri/milo.key)
97-
98-
# Automated release
99-
pnpm release v0.1.9
100-
```
101-
94+
See [`RELEASE.md`](RELEASE.md) for complete release instructions.
10295

10396
### 📁 Project Structure
10497

RELEASE.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# 🚀 Release Guide
2+
3+
Complete guide for releasing new versions of Milo with auto-updates.
4+
5+
## Quick Release
6+
7+
```bash
8+
# 1. Export signing key
9+
export TAURI_SIGNING_PRIVATE_KEY=$(cat ~/.tauri/milo.key)
10+
11+
# 2. Run automated release
12+
pnpm release v0.1.13
13+
14+
# 3. Push to GitHub
15+
git push origin master && git push origin v0.1.13
16+
17+
# 4. Create GitHub release and upload files (see below)
18+
```
19+
20+
## 📁 File Locations After Build
21+
22+
After running `pnpm release v0.1.13`, you'll find these files:
23+
24+
### **For User Downloads:**
25+
```
26+
src-tauri/target/release/bundle/dmg/
27+
└── Milo_0.1.13_x64.dmg
28+
```
29+
30+
### **For Auto-Updates:**
31+
```
32+
src-tauri/target/release/bundle/macos/
33+
├── Milo.app.tar.gz
34+
└── Milo.app.tar.gz.sig
35+
```
36+
37+
### **Update Manifest:**
38+
```
39+
project-root/
40+
└── latest.json
41+
```
42+
43+
## 📤 GitHub Release Upload
44+
45+
Create a new release on GitHub and upload these files:
46+
47+
1. **`Milo_0.1.13_x64.dmg`** (from `/dmg/` folder)
48+
- For users to download and install
49+
50+
2. **`Milo.app.tar.gz`** (from `/macos/` folder)
51+
- For automatic updates
52+
53+
3. **`latest.json`** (from project root)
54+
- Update manifest (tells app about new version)
55+
56+
## 🔐 First Time Setup
57+
58+
### Generate Signing Key (Once)
59+
```bash
60+
pnpm tauri signer generate -w ~/.tauri/milo.key --password test123
61+
```
62+
63+
### Back Up Your Key
64+
**CRITICAL:** Store these securely in your password manager:
65+
- File: `~/.tauri/milo.key`
66+
- Password: `test123`
67+
- Note: "Required for Milo app updates. If lost, cannot release updates."
68+
69+
## 🎯 What Each Script Does
70+
71+
### `pnpm release v0.1.13`
72+
1.**Validates signing key** setup
73+
2.**Updates versions** in `Cargo.toml`, `package.json`, `tauri.conf.json`
74+
3.**Builds app** with cryptographic signatures
75+
4.**Extracts signatures** from build artifacts
76+
5.**Generates latest.json** with update information
77+
6.**Commits and tags** (optional)
78+
79+
## 🔍 Troubleshooting
80+
81+
### "Signing key not found"
82+
```bash
83+
# Generate new key
84+
pnpm tauri signer generate -w ~/.tauri/milo.key --password test123
85+
```
86+
87+
### "Environment variables not set"
88+
```bash
89+
# Set signing key
90+
export TAURI_SIGNING_PRIVATE_KEY=$(cat ~/.tauri/milo.key)
91+
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="test123"
92+
```
93+
94+
### "Build failed"
95+
- Ensure all dependencies installed: `pnpm install`
96+
- Check Rust toolchain: `rustup update`
97+
- Verify key permissions: `ls -la ~/.tauri/milo.key`
98+
99+
### "No signature files found"
100+
- Build completed but signatures missing
101+
- Manual signatures will be created in `latest.json`
102+
- Check that `createUpdaterArtifacts: true` in `tauri.conf.json`
103+
104+
## 🎉 Auto-Update Flow
105+
106+
1. **User has** Milo v0.1.12 installed
107+
2. **You release** v0.1.13 using this process
108+
3. **App checks** `latest.json` on startup
109+
4. **Shows update** notification if newer version found
110+
5. **Downloads** `Milo.app.tar.gz` automatically
111+
6. **Installs** and restarts with new version
112+
113+
## 📋 Release Checklist
114+
115+
- [ ] Signing key backed up securely
116+
- [ ] Environment variables set
117+
- [ ] Version number follows semantic versioning
118+
- [ ] Run `pnpm release vX.X.X`
119+
- [ ] Review generated `latest.json`
120+
- [ ] Push to GitHub: `git push origin master && git push origin vX.X.X`
121+
- [ ] Create GitHub release
122+
- [ ] Upload DMG file from `/dmg/` folder
123+
- [ ] Upload `Milo.app.tar.gz` from `/macos/` folder
124+
- [ ] Upload `latest.json` from project root
125+
- [ ] Test auto-update on previous version
126+
127+
## 🤖 Alternative: Automated Releases
128+
129+
For fully automated releases, set up GitHub Actions with:
130+
- `TAURI_SIGNING_PRIVATE_KEY` (base64 encoded key)
131+
- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`
132+
133+
Then releases happen automatically on git tag push!

src-tauri/src/core.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use tauri::Manager;
1+
use tauri::{Manager, Emitter};
22
use arboard::Clipboard;
33

44
use crate::transform::transform_text;
@@ -54,8 +54,9 @@ pub async fn transform_clipboard(
5454
cleaned_transformed,
5555
)?;
5656

57-
// Success! Don't show notification - causes crashes on macOS
58-
// User will see the transformed text in their clipboard
57+
// Emit success notification
58+
let notification_message = format!("Successfully transformed with \"{}\" tone", prompt_key);
59+
let _ = handle.emit("transformation_complete", notification_message);
5960

6061
Ok(())
6162
}

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
"productName": "Milo",
2222
"mainBinaryName": "Milo",
23-
"version": "0.1.12",
23+
"version": "0.1.11",
2424
"identifier": "com.milo.dev",
2525
"plugins": {
2626
"updater": {

src/App.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,18 @@ function App() {
8181
await invoke("transform_clipboard", {
8282
promptKey: currentSettings.selected_tone || "Improve Writing",
8383
});
84-
84+
8585
console.log("Clipboard transformation complete");
8686
} catch (error) {
8787
console.error("Failed to transform clipboard:", error);
88+
89+
// Show error notification to user
90+
const errorMessage = error instanceof Error ? error.message : String(error);
91+
sendNotification({
92+
title: 'Milo - Transform Error',
93+
body: errorMessage,
94+
icon: '/icon.png'
95+
});
8896
}
8997
});
9098

src/components/ApiSettings.tsx

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,36 @@ export function Settings() {
177177
toggleEnabled();
178178
};
179179

180+
const deleteUsageKey = async () => {
181+
const userConfirmed = await ask('Are you sure you want to delete your usage key? You will need to enter a new one to use Milo.', {
182+
title: 'Delete Usage Key',
183+
kind: 'warning'
184+
});
185+
186+
if (userConfirmed) {
187+
try {
188+
setSaving(true);
189+
await invoke('save_litellm_api_key', { key: '' });
190+
setUsageKey('');
191+
setUsageKeyPreview('');
192+
setHasKey(false);
193+
await message('Usage key deleted successfully!', { title: 'Success', kind: 'info' });
194+
} catch (error) {
195+
console.error('Failed to delete usage key:', error);
196+
await message('Failed to delete usage key. Please try again.', { title: 'Error', kind: 'error' });
197+
} finally {
198+
setSaving(false);
199+
}
200+
}
201+
};
202+
203+
180204
const clearHistory = async () => {
181205
const userConfirmed = await ask('Are you sure you want to clear all transformation history? This action cannot be undone.', {
182206
title: 'Clear History',
183207
kind: 'warning'
184208
});
185-
209+
186210
if (userConfirmed) {
187211
try {
188212
await invoke('clear_transformation_history');
@@ -220,25 +244,23 @@ export function Settings() {
220244
<div className="bg-background-secondary p-6 rounded-lg border border-border-primary">
221245
<div className="mb-4">
222246
<h2 className="text-lg text-text-primary">Usage Key</h2>
223-
<p className="text-sm text-text-secondary">Your key for accessing text transformations</p>
247+
<p className="text-sm text-text-secondary">
248+
{!hasKey ? "You need a usage key to transform text with Milo" : "Your key for accessing text transformations"}
249+
</p>
224250
</div>
225251

226252
<div className="space-y-4">
227253
{!hasKey ? (
228254
/* No Key State */
229-
<div className="text-center space-y-4">
230-
<div className="inline-flex items-center px-3 py-1 rounded-full text-xs bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400">
231-
<div className="w-2 h-2 bg-red-500 rounded-full mr-2"></div>
232-
Not Ready
233-
</div>
234-
235-
<div className="bg-accent-primary/10 border border-accent-primary/30 rounded-lg p-4">
236-
<p className="text-sm text-text-primary mb-3">
237-
You need a usage key to transform text with Milo.
238-
</p>
255+
<div className="space-y-4">
256+
<div className="flex items-center justify-between">
257+
<div className="inline-flex items-center px-3 py-1 rounded-full text-xs bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400">
258+
<div className="w-2 h-2 bg-red-500 rounded-full mr-2"></div>
259+
Not Ready
260+
</div>
239261
<button
240262
onClick={openWebsite}
241-
className="inline-flex items-center px-4 py-2 bg-accent-primary text-white text-sm rounded-lg hover:bg-accent-secondary transition-colors"
263+
className="inline-flex items-center px-3 py-2 bg-accent-primary text-white text-sm rounded-lg hover:bg-accent-secondary transition-colors"
242264
>
243265
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
244266
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
@@ -256,7 +278,7 @@ export function Settings() {
256278
type="password"
257279
value={usageKey}
258280
onChange={(e) => setUsageKey(e.target.value)}
259-
placeholder="milo-..."
281+
placeholder="sk-..."
260282
className="w-full px-3 py-2 border border-border-primary rounded-lg focus:ring-2 focus:ring-accent-primary focus:border-accent-primary bg-background-primary text-text-primary"
261283
/>
262284
<button
@@ -276,6 +298,12 @@ export function Settings() {
276298
<div className="w-2 h-2 bg-green-500 rounded-full mr-2"></div>
277299
Ready
278300
</div>
301+
<button
302+
onClick={deleteUsageKey}
303+
className="px-3 py-1.5 text-xs text-text-secondary hover:text-text-primary transition-colors"
304+
>
305+
Delete
306+
</button>
279307
</div>
280308

281309
<div className="bg-background-tertiary p-3 rounded-lg border border-border-primary">

0 commit comments

Comments
 (0)