proti0070 commited on
Commit
7624539
·
verified ·
1 Parent(s): 67b521d

Update start.sh

Browse files
Files changed (1) hide show
  1. start.sh +206 -78
start.sh CHANGED
@@ -15,6 +15,26 @@ Xvfb :99 -screen 0 1280x800x16 -ac &
15
  sleep 3
16
 
17
  echo "Starting Openbox..."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  openbox --replace &
19
 
20
  sleep 2
@@ -27,38 +47,159 @@ sleep 5
27
  echo "Starting VNC..."
28
  x11vnc -display :99 -nopw -forever -shared -rfbport 5900 -defer 10 -wait 10 -q &
29
 
30
- # Wait for VNC to be ready
31
  sleep 3
32
 
33
- # Create the main index.html with correct HF Spaces WebSocket path
34
  cat > /usr/share/novnc/index.html << 'EOF'
35
  <!DOCTYPE html>
36
  <html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  <head>
38
  <title>Android Studio on Hugging Face</title>
39
  <meta charset="utf-8">
40
  <style>
41
- body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #1e1e1e; color: #fff; height: 100vh; display: flex; flex-direction: column; }
42
- .header { display: flex; justify-content: space-between; align-items: center; padding: 10px 20px; background: #2d2d2d; border-bottom: 2px solid #3ddc84; }
43
- .title h1 { margin: 0; font-size: 1.3rem; color: #3ddc84; }
44
- .badge { background: #3ddc84; color: #000; padding: 2px 8px; border-radius: 12px; font-size: 0.7rem; font-weight: bold; margin-left: 10px; }
45
- .controls { display: flex; gap: 8px; align-items: center; }
46
- button { background: #3ddc84; color: #000; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 0.8rem; }
47
- button.secondary { background: transparent; color: #3ddc84; border: 1px solid #3ddc84; }
48
- button:disabled { opacity: 0.5; cursor: not-allowed; }
49
- .vnc-container { flex: 1; background: #000; position: relative; overflow: hidden; }
50
- #vnc { width: 100%; height: 100%; }
51
- .status { display: flex; align-items: center; gap: 5px; margin-right: 15px; font-size: 0.8rem; }
52
- .status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
53
- .status-dot.connected { background: #3ddc84; animation: pulse 2s infinite; }
54
- .status-dot.connecting { background: #ffaa00; }
55
- .status-dot.disconnected { background: #ff4444; }
56
- @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(61, 220, 132, 0.7); } 70% { box-shadow: 0 0 0 6px rgba(61, 220, 132, 0); } }
57
- .loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; z-index: 10; background: rgba(30,30,30,0.9); padding: 20px; border-radius: 8px; border: 1px solid #3ddc84; }
58
- .spinner { border: 3px solid #f3f3f3; border-top: 3px solid #3ddc84; border-radius: 50%; width: 30px; height: 30px; animation: spin 1s linear infinite; margin: 0 auto 10px; }
59
- @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
60
- .footer { text-align: center; padding: 5px; background: #2d2d2d; font-size: 0.7rem; color: #888; }
61
- .footer a { color: #3ddc84; text-decoration: none; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  </style>
63
  </head>
64
  <body>
@@ -87,10 +228,9 @@ cat > /usr/share/novnc/index.html << 'EOF'
87
  </div>
88
 
89
  <div class="footer">
90
- ⚡ Running on Hugging Face Spaces | <a href="#" onclick="toggleFullscreen()">Fullscreen</a> | <span id="ws-info"></span>
91
  </div>
92
 
93
- <script src="vnc.js"></script>
94
  <script>
95
  let rfb;
96
  let retryCount = 0;
@@ -102,7 +242,6 @@ cat > /usr/share/novnc/index.html << 'EOF'
102
  const statusText = document.getElementById('status-text');
103
  const viewOnlyBtn = document.getElementById('viewOnlyBtn');
104
  const ctrlAltDelBtn = document.getElementById('ctrlAltDelBtn');
105
- const wsInfo = document.getElementById('ws-info');
106
 
107
  function setStatus(state, message) {
108
  statusDot.className = 'status-dot ' + state;
@@ -136,18 +275,16 @@ cat > /usr/share/novnc/index.html << 'EOF'
136
 
137
  function connect() {
138
  loading.style.display = 'block';
 
139
  setStatus('connecting', 'Connecting...');
140
  viewOnlyBtn.disabled = true;
141
  ctrlAltDelBtn.disabled = true;
142
 
143
- // CORRECT WebSocket URL for Hugging Face Spaces
144
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
145
  const host = window.location.host;
146
-
147
- // For HF Spaces, the WebSocket endpoint is at /proxy/7860/websockify
148
  const wsUrl = `${protocol}//${host}/proxy/7860/websockify`;
149
 
150
- wsInfo.textContent = `Endpoint: /proxy/7860/websockify`;
151
  console.log('Connecting to:', wsUrl);
152
 
153
  try {
@@ -155,8 +292,7 @@ cat > /usr/share/novnc/index.html << 'EOF'
155
  credentials: { password: '' },
156
  shared: true,
157
  viewOnly: false,
158
- resizeSession: true,
159
- wsProtocols: ['binary']
160
  });
161
 
162
  rfb.addEventListener('connect', () => {
@@ -165,10 +301,9 @@ cat > /usr/share/novnc/index.html << 'EOF'
165
  viewOnlyBtn.disabled = false;
166
  ctrlAltDelBtn.disabled = false;
167
  retryCount = 0;
168
- console.log('Connected successfully');
169
  });
170
 
171
- rfb.addEventListener('disconnect', (e) => {
172
  loading.style.display = 'block';
173
  setStatus('disconnected', 'Disconnected');
174
  viewOnlyBtn.disabled = true;
@@ -186,13 +321,12 @@ cat > /usr/share/novnc/index.html << 'EOF'
186
 
187
  rfb.addEventListener('securityfailure', (e) => {
188
  console.error('Security failure:', e.detail);
189
- loadingText.textContent = 'Security error: ' + (e.detail.message || 'Unknown');
190
  });
191
 
192
  } catch (error) {
193
  console.error('Connection error:', error);
194
- loadingText.textContent = 'Connection error: ' + error.message;
195
- setStatus('disconnected', 'Error');
196
  }
197
  }
198
 
@@ -202,11 +336,12 @@ cat > /usr/share/novnc/index.html << 'EOF'
202
  if (rfb) setTimeout(() => rfb.resizeSession(), 100);
203
  });
204
  </script>
 
205
  </body>
206
  </html>
207
  EOF
208
 
209
- # Create a diagnostic page
210
  cat > /usr/share/novnc/diagnostic.html << 'EOF'
211
  <!DOCTYPE html>
212
  <html>
@@ -214,69 +349,57 @@ cat > /usr/share/novnc/diagnostic.html << 'EOF'
214
  <title>HF Space Diagnostic</title>
215
  <style>
216
  body { background: #1e1e1e; color: #fff; font-family: monospace; padding: 20px; }
 
217
  .success { color: #3ddc84; }
218
  .error { color: #ff4444; }
219
- pre { background: #2d2d2d; padding: 15px; border-radius: 5px; overflow: auto; }
220
- button { background: #3ddc84; color: #000; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; margin: 5px; }
221
  </style>
222
  </head>
223
  <body>
224
- <h1>🔧 Hugging Face Space Diagnostic Tool</h1>
225
- <button onclick="testWebSocket()">Test WebSocket Connection</button>
226
- <button onclick="checkVNC()">Check VNC Server</button>
227
- <div id="output"></div>
228
 
229
  <script>
230
  const output = document.getElementById('output');
231
 
232
- function log(msg, isError = false) {
233
- const div = document.createElement('div');
234
- div.className = isError ? 'error' : 'success';
235
- div.textContent = msg;
236
- output.appendChild(div);
237
- }
238
-
239
  async function testWebSocket() {
240
- output.innerHTML = '<pre>Testing WebSocket connections...</pre>';
241
-
242
- const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
243
- const host = window.location.host;
244
 
245
  const endpoints = [
246
  `/proxy/7860/websockify`,
247
- `/websockify`,
248
- `wss://${host}:7860/websockify`
249
  ];
250
 
251
  for (const endpoint of endpoints) {
252
- const url = endpoint.startsWith('ws') ? endpoint : `${protocol}//${host}${endpoint}`;
253
- log(`\nTesting: ${url}`);
 
 
254
 
255
  try {
256
  const ws = new WebSocket(url);
257
- const result = await new Promise((resolve, reject) => {
258
- ws.onopen = () => { ws.close(); resolve('✅ SUCCESS'); };
259
- ws.onerror = () => { reject(' FAILED'); };
260
- setTimeout(() => reject('⏱️ TIMEOUT'), 3000);
 
 
 
 
 
 
 
 
 
 
261
  });
262
- log(` ${result}`);
263
  } catch (e) {
264
- log(` ${e}`, true);
265
  }
266
  }
267
  }
268
-
269
- async function checkVNC() {
270
- output.innerHTML += '<pre>\nChecking VNC server...</pre>';
271
- log('Checking if VNC is running on port 5900...');
272
-
273
- try {
274
- const response = await fetch('/proxy/5900/');
275
- log('✅ VNC port is accessible');
276
- } catch (e) {
277
- log('❌ VNC port not accessible', true);
278
- }
279
- }
280
  </script>
281
  </body>
282
  </html>
@@ -285,5 +408,10 @@ EOF
285
  echo "Starting noVNC with HF Spaces configuration..."
286
  cd /usr/share/novnc
287
 
288
- # Bind to all interfaces and use correct port
 
 
 
 
 
289
  websockify --web=/usr/share/novnc 0.0.0.0:7860 localhost:5900
 
15
  sleep 3
16
 
17
  echo "Starting Openbox..."
18
+ # Create a minimal menu file to avoid the warning
19
+ mkdir -p /var/lib/openbox
20
+ cat > /var/lib/openbox/debian-menu.xml << 'EOF'
21
+ <?xml version="1.0" encoding="UTF-8"?>
22
+ <openbox_menu>
23
+ <menu id="root-menu" label="Openbox">
24
+ <item label="Android Studio">
25
+ <action name="Execute">
26
+ <command>/opt/android-studio/bin/studio.sh</command>
27
+ </action>
28
+ </item>
29
+ <item label="Terminal">
30
+ <action name="Execute">
31
+ <command>xterm</command>
32
+ </action>
33
+ </item>
34
+ </menu>
35
+ </openbox_menu>
36
+ EOF
37
+
38
  openbox --replace &
39
 
40
  sleep 2
 
47
  echo "Starting VNC..."
48
  x11vnc -display :99 -nopw -forever -shared -rfbport 5900 -defer 10 -wait 10 -q &
49
 
 
50
  sleep 3
51
 
52
+ # Create a simple landing page that redirects to vnc.html
53
  cat > /usr/share/novnc/index.html << 'EOF'
54
  <!DOCTYPE html>
55
  <html>
56
+ <head>
57
+ <meta http-equiv="refresh" content="0; url=/vnc.html">
58
+ <title>Redirecting to Android Studio VNC</title>
59
+ </head>
60
+ <body>
61
+ Redirecting to <a href="/vnc.html">Android Studio VNC</a>...
62
+ </body>
63
+ </html>
64
+ EOF
65
+
66
+ # Create a custom vnc.html that works with HF Spaces
67
+ cat > /usr/share/novnc/vnc.html << 'EOF'
68
+ <!DOCTYPE html>
69
+ <html>
70
  <head>
71
  <title>Android Studio on Hugging Face</title>
72
  <meta charset="utf-8">
73
  <style>
74
+ body {
75
+ margin: 0;
76
+ padding: 0;
77
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
78
+ background: #1e1e1e;
79
+ color: #fff;
80
+ height: 100vh;
81
+ display: flex;
82
+ flex-direction: column;
83
+ }
84
+ .header {
85
+ display: flex;
86
+ justify-content: space-between;
87
+ align-items: center;
88
+ padding: 10px 20px;
89
+ background: #2d2d2d;
90
+ border-bottom: 2px solid #3ddc84;
91
+ }
92
+ .title h1 {
93
+ margin: 0;
94
+ font-size: 1.3rem;
95
+ color: #3ddc84;
96
+ }
97
+ .badge {
98
+ background: #3ddc84;
99
+ color: #000;
100
+ padding: 2px 8px;
101
+ border-radius: 12px;
102
+ font-size: 0.7rem;
103
+ font-weight: bold;
104
+ margin-left: 10px;
105
+ }
106
+ .controls {
107
+ display: flex;
108
+ gap: 8px;
109
+ align-items: center;
110
+ }
111
+ button {
112
+ background: #3ddc84;
113
+ color: #000;
114
+ border: none;
115
+ padding: 6px 12px;
116
+ border-radius: 4px;
117
+ cursor: pointer;
118
+ font-weight: bold;
119
+ font-size: 0.8rem;
120
+ }
121
+ button.secondary {
122
+ background: transparent;
123
+ color: #3ddc84;
124
+ border: 1px solid #3ddc84;
125
+ }
126
+ button:disabled {
127
+ opacity: 0.5;
128
+ cursor: not-allowed;
129
+ }
130
+ .vnc-container {
131
+ flex: 1;
132
+ background: #000;
133
+ position: relative;
134
+ overflow: hidden;
135
+ }
136
+ #vnc {
137
+ width: 100%;
138
+ height: 100%;
139
+ }
140
+ .status {
141
+ display: flex;
142
+ align-items: center;
143
+ gap: 5px;
144
+ margin-right: 15px;
145
+ font-size: 0.8rem;
146
+ }
147
+ .status-dot {
148
+ width: 8px;
149
+ height: 8px;
150
+ border-radius: 50%;
151
+ display: inline-block;
152
+ }
153
+ .status-dot.connected {
154
+ background: #3ddc84;
155
+ animation: pulse 2s infinite;
156
+ }
157
+ .status-dot.connecting {
158
+ background: #ffaa00;
159
+ }
160
+ .status-dot.disconnected {
161
+ background: #ff4444;
162
+ }
163
+ @keyframes pulse {
164
+ 0% { box-shadow: 0 0 0 0 rgba(61, 220, 132, 0.7); }
165
+ 70% { box-shadow: 0 0 0 6px rgba(61, 220, 132, 0); }
166
+ }
167
+ .loading {
168
+ position: absolute;
169
+ top: 50%;
170
+ left: 50%;
171
+ transform: translate(-50%, -50%);
172
+ text-align: center;
173
+ z-index: 10;
174
+ background: rgba(30,30,30,0.9);
175
+ padding: 20px;
176
+ border-radius: 8px;
177
+ border: 1px solid #3ddc84;
178
+ }
179
+ .spinner {
180
+ border: 3px solid #f3f3f3;
181
+ border-top: 3px solid #3ddc84;
182
+ border-radius: 50%;
183
+ width: 30px;
184
+ height: 30px;
185
+ animation: spin 1s linear infinite;
186
+ margin: 0 auto 10px;
187
+ }
188
+ @keyframes spin {
189
+ 0% { transform: rotate(0deg); }
190
+ 100% { transform: rotate(360deg); }
191
+ }
192
+ .footer {
193
+ text-align: center;
194
+ padding: 5px;
195
+ background: #2d2d2d;
196
+ font-size: 0.7rem;
197
+ color: #888;
198
+ }
199
+ .footer a {
200
+ color: #3ddc84;
201
+ text-decoration: none;
202
+ }
203
  </style>
204
  </head>
205
  <body>
 
228
  </div>
229
 
230
  <div class="footer">
231
+ ⚡ Running on Hugging Face Spaces | <a href="#" onclick="toggleFullscreen()">Fullscreen</a>
232
  </div>
233
 
 
234
  <script>
235
  let rfb;
236
  let retryCount = 0;
 
242
  const statusText = document.getElementById('status-text');
243
  const viewOnlyBtn = document.getElementById('viewOnlyBtn');
244
  const ctrlAltDelBtn = document.getElementById('ctrlAltDelBtn');
 
245
 
246
  function setStatus(state, message) {
247
  statusDot.className = 'status-dot ' + state;
 
275
 
276
  function connect() {
277
  loading.style.display = 'block';
278
+ loadingText.textContent = 'Connecting to Android Studio...';
279
  setStatus('connecting', 'Connecting...');
280
  viewOnlyBtn.disabled = true;
281
  ctrlAltDelBtn.disabled = true;
282
 
283
+ // Hugging Face Spaces WebSocket endpoint
284
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
285
  const host = window.location.host;
 
 
286
  const wsUrl = `${protocol}//${host}/proxy/7860/websockify`;
287
 
 
288
  console.log('Connecting to:', wsUrl);
289
 
290
  try {
 
292
  credentials: { password: '' },
293
  shared: true,
294
  viewOnly: false,
295
+ resizeSession: true
 
296
  });
297
 
298
  rfb.addEventListener('connect', () => {
 
301
  viewOnlyBtn.disabled = false;
302
  ctrlAltDelBtn.disabled = false;
303
  retryCount = 0;
 
304
  });
305
 
306
+ rfb.addEventListener('disconnect', () => {
307
  loading.style.display = 'block';
308
  setStatus('disconnected', 'Disconnected');
309
  viewOnlyBtn.disabled = true;
 
321
 
322
  rfb.addEventListener('securityfailure', (e) => {
323
  console.error('Security failure:', e.detail);
324
+ loadingText.textContent = 'Security error';
325
  });
326
 
327
  } catch (error) {
328
  console.error('Connection error:', error);
329
+ loadingText.textContent = 'Connection error';
 
330
  }
331
  }
332
 
 
336
  if (rfb) setTimeout(() => rfb.resizeSession(), 100);
337
  });
338
  </script>
339
+ <script src="vnc.js"></script>
340
  </body>
341
  </html>
342
  EOF
343
 
344
+ # Create diagnostic page
345
  cat > /usr/share/novnc/diagnostic.html << 'EOF'
346
  <!DOCTYPE html>
347
  <html>
 
349
  <title>HF Space Diagnostic</title>
350
  <style>
351
  body { background: #1e1e1e; color: #fff; font-family: monospace; padding: 20px; }
352
+ pre { background: #2d2d2d; padding: 15px; border-radius: 5px; }
353
  .success { color: #3ddc84; }
354
  .error { color: #ff4444; }
355
+ button { background: #3ddc84; color: #000; border: none; padding: 10px; border-radius: 4px; cursor: pointer; margin: 5px; }
 
356
  </style>
357
  </head>
358
  <body>
359
+ <h1>🔧 Diagnostic Tool</h1>
360
+ <button onclick="testWebSocket()">Test WebSocket</button>
361
+ <button onclick="window.location.href='/vnc.html'">Go to VNC</button>
362
+ <pre id="output"></pre>
363
 
364
  <script>
365
  const output = document.getElementById('output');
366
 
 
 
 
 
 
 
 
367
  async function testWebSocket() {
368
+ output.textContent = 'Testing WebSocket connections...\n';
 
 
 
369
 
370
  const endpoints = [
371
  `/proxy/7860/websockify`,
372
+ `/websockify`
 
373
  ];
374
 
375
  for (const endpoint of endpoints) {
376
+ const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
377
+ const url = `${protocol}//${window.location.host}${endpoint}`;
378
+
379
+ output.textContent += `\nTesting: ${url}\n`;
380
 
381
  try {
382
  const ws = new WebSocket(url);
383
+ await new Promise((resolve, reject) => {
384
+ ws.onopen = () => {
385
+ output.textContent += ' SUCCESS\n';
386
+ ws.close();
387
+ resolve();
388
+ };
389
+ ws.onerror = () => {
390
+ output.textContent += '❌ FAILED\n';
391
+ reject();
392
+ };
393
+ setTimeout(() => {
394
+ output.textContent += '⏱️ TIMEOUT\n';
395
+ reject();
396
+ }, 3000);
397
  });
 
398
  } catch (e) {
399
+ output.textContent += `❌ ERROR: ${e.message}\n`;
400
  }
401
  }
402
  }
 
 
 
 
 
 
 
 
 
 
 
 
403
  </script>
404
  </body>
405
  </html>
 
408
  echo "Starting noVNC with HF Spaces configuration..."
409
  cd /usr/share/novnc
410
 
411
+ # Ensure vnc.js is available
412
+ if [ ! -f "vnc.js" ]; then
413
+ ln -sf /usr/share/novnc/vnc.js . 2>/dev/null || true
414
+ fi
415
+
416
+ # Start websockify
417
  websockify --web=/usr/share/novnc 0.0.0.0:7860 localhost:5900