-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbookmarklet.html
More file actions
254 lines (233 loc) · 10.5 KB
/
bookmarklet.html
File metadata and controls
254 lines (233 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Iris Bookmarklet - Save to Drive</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
line-height: 1.6;
}
h1 { color: #333; }
.bookmarklet {
background: #f5f5f5;
border: 2px dashed #999;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.bookmarklet a {
display: inline-block;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px 30px;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
font-size: 16px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
transition: transform 0.2s;
}
.bookmarklet a:hover {
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(0,0,0,0.15);
}
.instructions {
background: #e3f2fd;
border-left: 4px solid #2196f3;
padding: 15px;
margin: 20px 0;
}
.instructions ol {
margin: 10px 0;
padding-left: 20px;
}
.code {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
font-family: 'Monaco', 'Courier New', monospace;
font-size: 12px;
}
.warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 15px;
margin: 20px 0;
}
.success {
background: #d4edda;
border-left: 4px solid #28a745;
padding: 15px;
margin: 20px 0;
}
</style>
</head>
<body>
<h1>🌈 Iris - Save to Google Drive</h1>
<p>This bookmarklet lets you save selected text from claude.ai directly to Google Drive.</p>
<div class="bookmarklet">
<h2>📌 Drag this to your bookmarks bar:</h2>
<a href="javascript:(function(){const%20s=window.getSelection().toString()||document.body.innerText;if(!s){alert('No%20text%20selected!');return}const%20p=prompt('Save%20to%20Drive%20path:','notes/'+new%20Date().toISOString().split('T')[0]+'.txt');if(!p)return;const%20b=document.createElement('div');b.style.cssText='position:fixed;top:20px;right:20px;background:linear-gradient(135deg,%23667eea%200%,%23764ba2%20100%);color:white;padding:20px;border-radius:8px;box-shadow:0%204px%2012px%20rgba(0,0,0,0.3);z-index:999999;font-family:sans-serif;max-width:300px';b.innerHTML='<div%20style=%22font-weight:bold;margin-bottom:10px%22>💾%20Saving%20to%20Drive...</div><div%20style=%22font-size:12px;opacity:0.9%22>'+p+'</div>';document.body.appendChild(b);fetch('http://localhost:3001/api/drive/write',{method:'POST',headers:{'Content-Type':'application/json',Cookie:document.cookie},body:JSON.stringify({path:p,content:s})}).then(r=>r.json()).then(d=>{b.style.background='linear-gradient(135deg,%2328a745%200%,%2320c997%20100%)';b.innerHTML='<div%20style=%22font-weight:bold;margin-bottom:10px%22>✅%20Saved!</div><div%20style=%22font-size:12px;opacity:0.9%22>'+p+'</div><a%20href=%22'+d.webViewLink+'%22%20target=%22_blank%22%20style=%22color:white;text-decoration:underline;font-size:12px;display:block;margin-top:10px%22>Open%20in%20Drive%20→</a>';setTimeout(()=>b.remove(),5000)}).catch(e=>{b.style.background='linear-gradient(135deg,%23dc3545%200%,%23c82333%20100%)';b.innerHTML='<div%20style=%22font-weight:bold;margin-bottom:10px%22>❌%20Error</div><div%20style=%22font-size:11px%22>'+e.message+'</div><div%20style=%22font-size:10px;margin-top:10px;opacity:0.8%22>Is%20Iris%20HTTP%20server%20running?</div>';setTimeout(()=>b.remove(),7000)})})();">
💾 Save to Drive
</a>
<p style="font-size: 14px; color: #666; margin-top: 15px;">
← Drag this button to your bookmarks bar
</p>
</div>
<div class="instructions">
<h3>📖 How to Use</h3>
<ol>
<li><strong>Drag the button above</strong> to your browser's bookmarks bar</li>
<li><strong>Make sure Iris HTTP server is running:</strong>
<div class="code" style="margin: 10px 0;">npm run http</div>
</li>
<li><strong>Go to claude.ai</strong> and select some text</li>
<li><strong>Click the bookmarklet</strong> in your bookmarks bar</li>
<li><strong>Enter the Drive path</strong> when prompted (e.g., "notes/today.txt")</li>
<li><strong>Watch it save!</strong> 🎉</li>
</ol>
</div>
<div class="warning">
<h3>⚠️ Prerequisites</h3>
<ul>
<li>Iris HTTP server must be running on <code>localhost:3001</code></li>
<li>You must have completed OAuth setup (<code>npm run oauth</code>)</li>
<li>You must have configured browser session (<code>npm run setup:browser</code>)</li>
<li>You must be logged into claude.ai in the same browser</li>
</ul>
</div>
<div class="success">
<h3>✨ Features</h3>
<ul>
<li><strong>Smart defaults:</strong> Suggests today's date as filename</li>
<li><strong>Visual feedback:</strong> Shows save progress with animations</li>
<li><strong>Quick access:</strong> Click "Open in Drive" to view saved file</li>
<li><strong>Error handling:</strong> Clear messages if something goes wrong</li>
<li><strong>Auto-dismiss:</strong> Notification disappears after 5 seconds</li>
</ul>
</div>
<h2>🔧 Testing</h2>
<h3>1. Test HTTP Server First</h3>
<div class="code">
# In terminal
curl http://localhost:3001/health
</div>
<p>Should return: <code>{"status":"ok","service":"iris-http","mode":"browser",...}</code></p>
<h3>2. Test from Browser Console</h3>
<p>Open claude.ai, press F12, go to Console tab, paste:</p>
<div class="code">
fetch('http://localhost:3001/api/drive/list?path=Feannog', {
headers: { Cookie: document.cookie }
})
.then(r => r.json())
.then(d => console.log(d))
</div>
<h3>3. Test the Bookmarklet</h3>
<ol>
<li>Select some text on claude.ai</li>
<li>Click the bookmarklet</li>
<li>Enter a test path like "test/bookmarklet-test.txt"</li>
<li>Watch for success message!</li>
</ol>
<h2>📝 Unminified Code (For Reference)</h2>
<p>Here's what the bookmarklet does (formatted for readability):</p>
<div class="code">
(function() {
// Get selected text or entire page
const selectedText = window.getSelection().toString() || document.body.innerText;
if (!selectedText) {
alert('No text selected!');
return;
}
// Prompt for Drive path with smart default
const path = prompt(
'Save to Drive path:',
'notes/' + new Date().toISOString().split('T')[0] + '.txt'
);
if (!path) return;
// Show loading notification
const notification = document.createElement('div');
notification.style.cssText = 'position:fixed;top:20px;right:20px;' +
'background:linear-gradient(135deg, #667eea 0%, #764ba2 100%);' +
'color:white;padding:20px;border-radius:8px;' +
'box-shadow:0 4px 12px rgba(0,0,0,0.3);z-index:999999;' +
'font-family:sans-serif;max-width:300px';
notification.innerHTML =
'<div style="font-weight:bold;margin-bottom:10px">💾 Saving to Drive...</div>' +
'<div style="font-size:12px;opacity:0.9">' + path + '</div>';
document.body.appendChild(notification);
// Send to Iris HTTP server
fetch('http://localhost:3001/api/drive/write', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cookie': document.cookie // Pass session cookie
},
body: JSON.stringify({
path: path,
content: selectedText
})
})
.then(r => r.json())
.then(data => {
// Success!
notification.style.background =
'linear-gradient(135deg, #28a745 0%, #20c997 100%)';
notification.innerHTML =
'<div style="font-weight:bold;margin-bottom:10px">✅ Saved!</div>' +
'<div style="font-size:12px;opacity:0.9">' + path + '</div>' +
'<a href="' + data.webViewLink + '" target="_blank" ' +
'style="color:white;text-decoration:underline;font-size:12px;' +
'display:block;margin-top:10px">Open in Drive →</a>';
setTimeout(() => notification.remove(), 5000);
})
.catch(error => {
// Error
notification.style.background =
'linear-gradient(135deg, #dc3545 0%, #c82333 100%)';
notification.innerHTML =
'<div style="font-weight:bold;margin-bottom:10px">❌ Error</div>' +
'<div style="font-size:11px">' + error.message + '</div>' +
'<div style="font-size:10px;margin-top:10px;opacity:0.8">' +
'Is Iris HTTP server running?</div>';
setTimeout(() => notification.remove(), 7000);
});
})();
</div>
<h2>🐛 Troubleshooting</h2>
<h3>Server not responding?</h3>
<ul>
<li>Check Iris HTTP server is running: <code>npm run http</code></li>
<li>Verify it's on port 3001: <code>curl http://localhost:3001/health</code></li>
</ul>
<h3>401 Unauthorized error?</h3>
<ul>
<li>Session cookie expired - run <code>npm run setup:browser</code> again</li>
<li>Make sure you're logged into claude.ai</li>
<li>Restart HTTP server after updating session</li>
</ul>
<h3>CORS error?</h3>
<ul>
<li>HTTP server should allow claude.ai origin</li>
<li>Check server logs for CORS errors</li>
<li>Try from localhost:3000 instead (allowed in CORS config)</li>
</ul>
<h3>No text selected message?</h3>
<ul>
<li>Select text on the page before clicking bookmarklet</li>
<li>Or let it save entire page text (fallback)</li>
</ul>
<hr style="margin: 40px 0;">
<p style="text-align: center; color: #666;">
<strong>Iris HTTP Mode</strong> - v0.2.0 Prototype<br>
Made with 🌈 by Uncle Tallest & Vector
</p>
</body>
</html>