Lintottq commited on
Commit
f45dde1
·
verified ·
1 Parent(s): 36d9117

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +451 -19
index.html CHANGED
@@ -1,19 +1,451 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>Fitbit x Claude Voice Bridge</title>
7
+ <!-- FontAwesome for Icons -->
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+
10
+ <style>
11
+ :root {
12
+ --ios-bg: #F2F2F7;
13
+ --ios-card: #FFFFFF;
14
+ --ios-text: #1C1C1E;
15
+ --ios-gray: #8E8E93;
16
+ --fitbit-green: #00B0B9;
17
+ --claude-purple: #D97757; /* Anthropic orange-ish */
18
+ --claude-bg: #F9F7F3;
19
+ --accent-blue: #007AFF;
20
+ --shadow: 0 4px 20px rgba(0,0,0,0.08);
21
+ --font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
22
+ }
23
+
24
+ * {
25
+ box-sizing: box-sizing;
26
+ margin: 0;
27
+ padding: 0;
28
+ -webkit-tap-highlight-color: transparent;
29
+ }
30
+
31
+ body {
32
+ background-color: #e0e0e0;
33
+ font-family: var(--font-stack);
34
+ display: flex;
35
+ justify-content: center;
36
+ align-items: center;
37
+ min-height: 100vh;
38
+ overflow: hidden;
39
+ }
40
+
41
+ /* --- Phone Container --- */
42
+ .iphone-frame {
43
+ width: 375px;
44
+ height: 812px;
45
+ background: var(--ios-bg);
46
+ border-radius: 40px;
47
+ box-shadow: 0 20px 50px rgba(0,0,0,0.2);
48
+ position: relative;
49
+ overflow: hidden;
50
+ display: flex;
51
+ flex-direction: column;
52
+ border: 8px solid #333;
53
+ }
54
+
55
+ /* --- Header / Status Bar --- */
56
+ .status-bar {
57
+ height: 44px;
58
+ display: flex;
59
+ justify-content: space-between;
60
+ align-items: center;
61
+ padding: 0 20px;
62
+ font-size: 14px;
63
+ font-weight: 600;
64
+ color: var(--ios-text);
65
+ background: rgba(255, 255, 255, 0.8);
66
+ backdrop-filter: blur(10px);
67
+ z-index: 10;
68
+ }
69
+
70
+ .app-header {
71
+ padding: 10px 20px;
72
+ background: rgba(255, 255, 255, 0.9);
73
+ backdrop-filter: blur(20px);
74
+ border-bottom: 1px solid rgba(0,0,0,0.05);
75
+ display: flex;
76
+ justify-content: space-between;
77
+ align-items: center;
78
+ z-index: 9;
79
+ }
80
+
81
+ .app-title {
82
+ font-weight: 700;
83
+ font-size: 18px;
84
+ color: var(--ios-text);
85
+ }
86
+
87
+ .connection-status {
88
+ display: flex;
89
+ gap: 8px;
90
+ font-size: 12px;
91
+ color: var(--ios-gray);
92
+ }
93
+
94
+ .status-dot {
95
+ width: 8px;
96
+ height: 8px;
97
+ border-radius: 50%;
98
+ background-color: var(--fitbit-green);
99
+ box-shadow: 0 0 4px var(--fitbit-green);
100
+ animation: pulse 2s infinite;
101
+ }
102
+
103
+ /* --- Main Content Area --- */
104
+ .content-area {
105
+ flex: 1;
106
+ padding: 20px;
107
+ overflow-y: auto;
108
+ display: flex;
109
+ flex-direction: column;
110
+ gap: 15px;
111
+ }
112
+
113
+ /* Fitbit Data Card */
114
+ .fitbit-context {
115
+ background: linear-gradient(135deg, #00B0B9, #008a91);
116
+ color: white;
117
+ padding: 15px;
118
+ border-radius: 16px;
119
+ box-shadow: var(--shadow);
120
+ display: flex;
121
+ justify-content: space-between;
122
+ align-items: center;
123
+ }
124
+
125
+ .fitbit-label {
126
+ font-size: 12px;
127
+ opacity: 0.8;
128
+ text-transform: uppercase;
129
+ letter-spacing: 1px;
130
+ }
131
+
132
+ .fitbit-data {
133
+ font-size: 20px;
134
+ font-weight: 700;
135
+ }
136
+
137
+ .heart-icon {
138
+ font-size: 16px;
139
+ animation: heartbeat 1.2s infinite;
140
+ }
141
+
142
+ /* Claude Response Card */
143
+ .claude-card {
144
+ background: var(--claude-bg);
145
+ border: 1px solid rgba(0,0,0,0.05);
146
+ padding: 15px;
147
+ border-radius: 16px;
148
+ font-size: 14px;
149
+ line-height: 1.5;
150
+ color: #333;
151
+ box-shadow: var(--shadow);
152
+ position: relative;
153
+ display: none; /* Hidden by default */
154
+ }
155
+
156
+ .claude-card.active {
157
+ display: block;
158
+ animation: slideUp 0.4s ease-out;
159
+ }
160
+
161
+ .claude-header {
162
+ font-size: 10px;
163
+ color: var(--claude-purple);
164
+ font-weight: 700;
165
+ text-transform: uppercase;
166
+ margin-bottom: 5px;
167
+ display: flex;
168
+ align-items: center;
169
+ gap: 5px;
170
+ }
171
+
172
+ /* --- Voice Interaction Zone --- */
173
+ .voice-zone {
174
+ margin-top: auto;
175
+ margin-bottom: 20px;
176
+ display: flex;
177
+ flex-direction: column;
178
+ align-items: center;
179
+ justify-content: center;
180
+ height: 180px;
181
+ }
182
+
183
+ .mic-button {
184
+ width: 80px;
185
+ height: 80px;
186
+ background: white;
187
+ border-radius: 50%;
188
+ display: flex;
189
+ justify-content: center;
190
+ align-items: center;
191
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
192
+ cursor: pointer;
193
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
194
+ position: relative;
195
+ z-index: 2;
196
+ }
197
+
198
+ .mic-button i {
199
+ font-size: 24px;
200
+ color: var(--ios-text);
201
+ transition: color 0.3s;
202
+ }
203
+
204
+ .mic-button.listening {
205
+ background: var(--accent-blue);
206
+ transform: scale(1.1);
207
+ }
208
+
209
+ .mic-button.listening i {
210
+ color: white;
211
+ }
212
+
213
+ /* Ripple Effect */
214
+ .ripple {
215
+ position: absolute;
216
+ width: 80px;
217
+ height: 80px;
218
+ border-radius: 50%;
219
+ border: 2px solid var(--accent-blue);
220
+ opacity: 0;
221
+ z-index: 1;
222
+ }
223
+
224
+ .mic-button.listening .ripple {
225
+ animation: rippleAnim 1.5s infinite;
226
+ }
227
+
228
+ .voice-status-text {
229
+ margin-top: 15px;
230
+ font-size: 14px;
231
+ color: var(--ios-gray);
232
+ font-weight: 500;
233
+ height: 20px;
234
+ }
235
+
236
+ /* --- Footer --- */
237
+ .footer-link {
238
+ position: absolute;
239
+ bottom: 10px;
240
+ width: 100%;
241
+ text-align: center;
242
+ font-size: 10px;
243
+ color: var(--ios-gray);
244
+ opacity: 0.6;
245
+ }
246
+
247
+ .footer-link a {
248
+ color: var(--ios-text);
249
+ text-decoration: none;
250
+ font-weight: 600;
251
+ }
252
+
253
+ /* --- Animations --- */
254
+ @keyframes pulse {
255
+ 0% { opacity: 0.5; }
256
+ 50% { opacity: 1; }
257
+ 100% { opacity: 0.5; }
258
+ }
259
+
260
+ @keyframes heartbeat {
261
+ 0% { transform: scale(1); }
262
+ 14% { transform: scale(1.3); }
263
+ 28% { transform: scale(1); }
264
+ 42% { transform: scale(1.3); }
265
+ 70% { transform: scale(1); }
266
+ }
267
+
268
+ @keyframes rippleAnim {
269
+ 0% { width: 80px; height: 80px; opacity: 1; }
270
+ 100% { width: 200px; height: 200px; opacity: 0; }
271
+ }
272
+
273
+ @keyframes slideUp {
274
+ from { transform: translateY(20px); opacity: 0; }
275
+ to { transform: translateY(0); opacity: 1; }
276
+ }
277
+
278
+ /* --- Loading Bar --- */
279
+ .loading-bar {
280
+ height: 2px;
281
+ width: 100%;
282
+ background: #eee;
283
+ position: relative;
284
+ overflow: hidden;
285
+ display: none;
286
+ }
287
+
288
+ .loading-bar.active {
289
+ display: block;
290
+ }
291
+
292
+ .loading-progress {
293
+ height: 100%;
294
+ width: 50%;
295
+ background: var(--fitbit-green);
296
+ position: absolute;
297
+ animation: load 1.5s infinite ease-in-out;
298
+ }
299
+
300
+ @keyframes load {
301
+ 0% { left: -50%; }
302
+ 100% { left: 100%; }
303
+ }
304
+
305
+ </style>
306
+ </head>
307
+ <body>
308
+
309
+ <div class="iphone-frame">
310
+ <!-- iOS Status Bar Simulation -->
311
+ <div class="status-bar">
312
+ <span>9:41</span>
313
+ <div style="display: flex; gap: 5px;">
314
+ <i class="fas fa-signal"></i>
315
+ <i class="fas fa-wifi"></i>
316
+ <i class="fas fa-battery-three-quarters"></i>
317
+ </div>
318
+ </div>
319
+
320
+ <!-- App Header -->
321
+ <div class="app-header">
322
+ <div class="app-title">Fitbit<span style="color:var(--fitbit-green)">Voice</span></div>
323
+ <div class="connection-status">
324
+ <span>Fitbit</span>
325
+ <div class="status-dot"></div>
326
+ <span>Claude</span>
327
+ <i class="fas fa-check-circle" style="color: var(--claude-purple)"></i>
328
+ </div>
329
+ </div>
330
+
331
+ <!-- Main Scrollable Content -->
332
+ <div class="content-area" id="chat-container">
333
+
334
+ <!-- Context Card: Simulates Fitbit Data being sent -->
335
+ <div class="fitbit-context">
336
+ <div>
337
+ <div class="fitbit-label">Current Activity</div>
338
+ <div class="fitbit-data">Walking <span style="font-size: 14px; opacity: 0.8">• 102 bpm</span></div>
339
+ </div>
340
+ <i class="fas fa-heartbeat heart-icon"></i>
341
+ </div>
342
+
343
+ <!-- Claude Response Placeholder -->
344
+ <div class="claude-card" id="claude-response">
345
+ <div class="claude-header">
346
+ <i class="fas fa-sparkles"></i> Claude AI
347
+ </div>
348
+ <div id="claude-text">
349
+ Waiting for command...
350
+ </div>
351
+ </div>
352
+
353
+ </div>
354
+
355
+ <!-- Loading Bar -->
356
+ <div class="loading-bar" id="loader">
357
+ <div class="loading-progress"></div>
358
+ </div>
359
+
360
+ <!-- Voice Control Area -->
361
+ <div class="voice-zone">
362
+ <div class="voice-status-text" id="status-text">Tap to speak</div>
363
+
364
+ <div class="mic-button" id="mic-btn" onclick="toggleRecording()">
365
+ <i class="fas fa-microphone"></i>
366
+ <div class="ripple"></div>
367
+ </div>
368
+ </div>
369
+
370
+ <!-- Footer Link -->
371
+ <div class="footer-link">
372
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
373
+ </div>
374
+ </div>
375
+
376
+ <script>
377
+ const micBtn = document.getElementById('mic-btn');
378
+ const statusText = document.getElementById('status-text');
379
+ const claudeCard = document.getElementById('claude-response');
380
+ const claudeText = document.getElementById('claude-text');
381
+ const loader = document.getElementById('loader');
382
+ const chatContainer = document.getElementById('chat-container');
383
+
384
+ let isRecording = false;
385
+
386
+ // Mock responses for demonstration
387
+ const mockResponses = [
388
+ "I've logged your 'Walking' activity. Your heart rate is slightly elevated at 102 bpm. Is this a new workout session?",
389
+ "Based on your Fitbit data, you've taken 4,200 steps today. You are 60% towards your daily goal. Keep moving!",
390
+ "I noticed a spike in your heart rate at 9:30 AM. Did you just finish a sprint? I can add that to your exercise log."
391
+ ];
392
+
393
+ function toggleRecording() {
394
+ if (isRecording) {
395
+ stopRecording();
396
+ } else {
397
+ startRecording();
398
+ }
399
+ }
400
+
401
+ function startRecording() {
402
+ isRecording = true;
403
+ micBtn.classList.add('listening');
404
+ statusText.innerText = "Listening...";
405
+ statusText.style.color = "#007AFF";
406
+
407
+ // Simulate listening duration (3 seconds)
408
+ setTimeout(() => {
409
+ processCommand();
410
+ }, 3000);
411
+ }
412
+
413
+ function stopRecording() {
414
+ isRecording = false;
415
+ micBtn.classList.remove('listening');
416
+ statusText.innerText = "Tap to speak";
417
+ statusText.style.color = "#8E8E93";
418
+ }
419
+
420
+ function processCommand() {
421
+ stopRecording();
422
+
423
+ // 1. Show Loading State (Sending to Claude)
424
+ loader.classList.add('active');
425
+ statusText.innerText = "Processing with Claude...";
426
+ statusText.style.color = "#D97757"; // Claude color
427
+
428
+ // 2. Simulate Network Delay
429
+ setTimeout(() => {
430
+ loader.classList.remove('active');
431
+
432
+ // 3. Generate Response
433
+ const randomResponse = mockResponses[Math.floor(Math.random() * mockResponses.length)];
434
+
435
+ // 4. Update UI with Response
436
+ claudeText.innerText = randomResponse;
437
+ claudeCard.classList.add('active');
438
+
439
+ statusText.innerText = "Command Sent";
440
+
441
+ // Scroll to bottom
442
+ chatContainer.scrollTop = chatContainer.scrollHeight;
443
+
444
+ }, 2000);
445
+ }
446
+
447
+ // Initialize
448
+ console.log("Fitbit-Claude Bridge Initialized");
449
+ </script>
450
+ </body>
451
+ </html>