srinetwork commited on
Commit
c1edcb4
·
verified ·
1 Parent(s): eb63f46

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +366 -60
Dockerfile CHANGED
@@ -77,7 +77,7 @@ echo "✅ Auto-backup enabled (every 5 minutes)"
77
  echo ""
78
 
79
  # ==========================================
80
- # WEB TERMINAL SERVER (Pterodactyl Style)
81
  # ==========================================
82
  cat > /app/web_terminal.py << 'PYTHON_SCRIPT'
83
  import os
@@ -152,16 +152,16 @@ def start_minecraft():
152
 
153
  threading.Thread(target=process_commands, daemon=True).start()
154
 
155
- HTML_TEMPLATE = '''
156
  <!DOCTYPE html>
157
  <html lang="en">
158
  <head>
159
  <meta charset="UTF-8">
160
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
161
  <title>Minecraft Server - Web Console</title>
162
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
163
  <style>
164
- * { margin: 0; padding: 0; box-sizing: border-box; }
165
 
166
  body {
167
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
@@ -169,31 +169,39 @@ HTML_TEMPLATE = '''
169
  color: #e0e0e0;
170
  height: 100vh;
171
  overflow: hidden;
 
172
  }
173
 
 
 
174
  /* Top Navigation */
175
  .top-nav {
176
  background: #252a30;
177
  border-bottom: 1px solid #363b42;
178
- padding: 0 20px;
179
  display: flex;
180
  align-items: center;
181
  height: 50px;
 
 
182
  }
183
 
184
- .nav-tabs { display: flex; gap: 0; height: 100%; }
 
185
 
186
  .nav-tab {
187
- padding: 0 20px;
188
  display: flex;
189
  align-items: center;
190
- gap: 8px;
191
  color: #9ca3af;
192
  text-decoration: none;
193
- font-size: 14px;
194
  border-bottom: 2px solid transparent;
195
  transition: all 0.2s;
196
  cursor: pointer;
 
 
197
  }
198
 
199
  .nav-tab:hover { color: #e0e0e0; background: rgba(255,255,255,0.05); }
@@ -204,7 +212,7 @@ HTML_TEMPLATE = '''
204
  margin-left: auto;
205
  display: flex;
206
  align-items: center;
207
- gap: 10px;
208
  }
209
 
210
  .nav-btn {
@@ -215,12 +223,21 @@ HTML_TEMPLATE = '''
215
  cursor: pointer;
216
  border-radius: 4px;
217
  transition: all 0.2s;
 
 
 
 
 
218
  }
219
 
220
  .nav-btn:hover { color: #fff; background: rgba(255,255,255,0.1); }
221
 
222
  /* Main Layout */
223
- .main-container { display: flex; height: calc(100vh - 50px); }
 
 
 
 
224
 
225
  /* Console Area */
226
  .console-section {
@@ -228,41 +245,50 @@ HTML_TEMPLATE = '''
228
  display: flex;
229
  flex-direction: column;
230
  background: #0d1117;
 
231
  }
232
 
233
  .console-header {
234
  background: #161b22;
235
- padding: 15px 20px;
236
  border-bottom: 1px solid #30363d;
237
  display: flex;
238
  justify-content: space-between;
239
  align-items: center;
 
 
240
  }
241
 
242
  .server-title {
243
- font-size: 20px;
244
  font-weight: 600;
245
  color: #f0f6fc;
246
  display: flex;
247
  align-items: center;
248
- gap: 10px;
249
  }
250
 
251
- .server-title i { color: #3b82f6; }
252
 
253
- .control-buttons { display: flex; gap: 8px; }
 
 
 
 
254
 
255
  .btn {
256
- padding: 8px 16px;
257
  border: none;
258
- border-radius: 4px;
259
- font-size: 13px;
260
  font-weight: 500;
261
  cursor: pointer;
262
  display: flex;
263
  align-items: center;
264
- gap: 6px;
265
  transition: all 0.2s;
 
 
266
  }
267
 
268
  .btn-primary { background: #2563eb; color: white; }
@@ -285,14 +311,15 @@ HTML_TEMPLATE = '''
285
  .terminal {
286
  width: 100%;
287
  height: 100%;
288
- padding: 15px;
289
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
290
- font-size: 13px;
291
  line-height: 1.5;
292
  color: #e6edf3;
293
  overflow-y: auto;
294
  white-space: pre-wrap;
295
  word-wrap: break-word;
 
296
  }
297
 
298
  .terminal-line { margin: 2px 0; padding: 1px 0; }
@@ -305,9 +332,9 @@ HTML_TEMPLATE = '''
305
  .command-area {
306
  background: #161b22;
307
  border-top: 1px solid #30363d;
308
- padding: 12px 20px;
309
  display: flex;
310
- gap: 10px;
311
  align-items: center;
312
  }
313
 
@@ -318,22 +345,24 @@ HTML_TEMPLATE = '''
318
  background: #0d1117;
319
  border: 1px solid #30363d;
320
  border-radius: 6px;
321
- padding: 0 15px;
322
  transition: border-color 0.2s;
 
323
  }
324
 
325
  .command-input-wrapper:focus-within { border-color: #58a6ff; }
326
- .command-input-wrapper i { color: #6e7681; margin-right: 10px; }
327
 
328
  #commandInput {
329
  flex: 1;
330
  background: transparent;
331
  border: none;
332
  color: #e6edf3;
333
- padding: 12px 0;
334
  font-size: 14px;
335
  font-family: 'SFMono-Regular', Consolas, monospace;
336
  outline: none;
 
337
  }
338
 
339
  #commandInput::placeholder { color: #6e7681; }
@@ -342,14 +371,17 @@ HTML_TEMPLATE = '''
342
  background: #238636;
343
  color: white;
344
  border: none;
345
- padding: 12px 24px;
346
  border-radius: 6px;
347
  cursor: pointer;
348
  font-weight: 500;
349
  display: flex;
350
  align-items: center;
351
- gap: 6px;
352
  transition: background 0.2s;
 
 
 
353
  }
354
 
355
  .send-btn:hover { background: #2ea043; }
@@ -357,35 +389,37 @@ HTML_TEMPLATE = '''
357
 
358
  /* Sidebar */
359
  .sidebar {
360
- width: 300px;
361
  background: #1f2428;
362
  border-left: 1px solid #363b42;
363
- padding: 20px;
364
  overflow-y: auto;
 
365
  }
366
 
367
  .stat-card {
368
  background: #252a30;
369
  border: 1px solid #363b42;
370
  border-radius: 8px;
371
- padding: 16px;
372
- margin-bottom: 12px;
373
  display: flex;
374
  align-items: center;
375
- gap: 15px;
376
  transition: transform 0.2s, box-shadow 0.2s;
377
  }
378
 
379
  .stat-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
380
 
381
  .stat-icon {
382
- width: 45px;
383
- height: 45px;
384
  border-radius: 8px;
385
  display: flex;
386
  align-items: center;
387
  justify-content: center;
388
- font-size: 20px;
 
389
  }
390
 
391
  .stat-icon.blue { background: rgba(59, 130, 246, 0.2); color: #3b82f6; }
@@ -395,19 +429,19 @@ HTML_TEMPLATE = '''
395
  .stat-icon.purple { background: rgba(168, 85, 247, 0.2); color: #a855f7; }
396
  .stat-icon.cyan { background: rgba(6, 182, 212, 0.2); color: #06b6d4; }
397
 
398
- .stat-info { flex: 1; }
399
- .stat-label { font-size: 12px; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
400
- .stat-value { font-size: 18px; font-weight: 600; color: #f0f6fc; }
401
- .stat-sub { font-size: 11px; color: #6b7280; margin-top: 2px; }
402
 
403
  /* Status Badge */
404
  .status-indicator {
405
  display: inline-flex;
406
  align-items: center;
407
- gap: 6px;
408
- padding: 4px 10px;
409
  border-radius: 20px;
410
- font-size: 11px;
411
  font-weight: 600;
412
  text-transform: uppercase;
413
  }
@@ -416,13 +450,13 @@ HTML_TEMPLATE = '''
416
  .status-offline { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
417
  .status-starting { background: rgba(234, 179, 8, 0.2); color: #eab308; }
418
 
419
- .pulse { width: 8px; height: 8px; border-radius: 50%; background: currentColor; animation: pulse 2s infinite; }
420
  @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
421
 
422
  /* Scrollbar */
423
- ::-webkit-scrollbar { width: 8px; height: 8px; }
424
  ::-webkit-scrollbar-track { background: #1a1d21; }
425
- ::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 4px; }
426
  ::-webkit-scrollbar-thumb:hover { background: #6b7280; }
427
 
428
  /* Connection Status */
@@ -430,20 +464,225 @@ HTML_TEMPLATE = '''
430
  position: fixed;
431
  top: 50px;
432
  left: 0;
433
- right: 300px;
434
- padding: 8px 20px;
435
- font-size: 12px;
436
  font-weight: 500;
437
  display: flex;
438
  align-items: center;
439
- gap: 8px;
440
- z-index: 100;
441
  transition: all 0.3s;
442
  }
443
 
444
  .connection-bar.connected { background: rgba(34, 197, 94, 0.15); color: #22c55e; border-bottom: 1px solid rgba(34, 197, 94, 0.3); }
445
  .connection-bar.disconnected { background: rgba(239, 68, 68, 0.15); color: #ef4444; border-bottom: 1px solid rgba(239, 68, 68, 0.3); }
446
  .connection-bar.connecting { background: rgba(234, 179, 8, 0.15); color: #eab308; border-bottom: 1px solid rgba(234, 179, 8, 0.3); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  </style>
448
  </head>
449
  <body>
@@ -463,6 +702,9 @@ HTML_TEMPLATE = '''
463
  </div>
464
  </nav>
465
 
 
 
 
466
  <!-- Main Container -->
467
  <div class="main-container">
468
  <!-- Console Section -->
@@ -482,13 +724,13 @@ HTML_TEMPLATE = '''
482
  </div>
483
  <div class="control-buttons">
484
  <button class="btn btn-primary" id="startBtn" onclick="sendCmd('start')" disabled>
485
- <i class="fas fa-play"></i> Start
486
  </button>
487
  <button class="btn btn-secondary" id="restartBtn" onclick="sendCmd('restart')" disabled>
488
- <i class="fas fa-redo"></i> Restart
489
  </button>
490
  <button class="btn btn-danger" id="stopBtn" onclick="sendCmd('stop')" disabled>
491
- <i class="fas fa-stop"></i> Stop
492
  </button>
493
  </div>
494
  </div>
@@ -503,13 +745,13 @@ HTML_TEMPLATE = '''
503
  <input type="text" id="commandInput" placeholder="Type a command..." autocomplete="off" disabled>
504
  </div>
505
  <button class="send-btn" id="sendBtn" onclick="sendInput()" disabled>
506
- <i class="fas fa-paper-plane"></i> Send
507
  </button>
508
  </div>
509
  </div>
510
 
511
  <!-- Sidebar -->
512
- <div class="sidebar">
513
  <div class="stat-card">
514
  <div class="stat-icon blue"><i class="fas fa-network-wired"></i></div>
515
  <div class="stat-info">
@@ -565,6 +807,11 @@ HTML_TEMPLATE = '''
565
  </div>
566
  </div>
567
  </div>
 
 
 
 
 
568
 
569
  <script>
570
  const terminal = document.getElementById('terminal');
@@ -574,12 +821,15 @@ HTML_TEMPLATE = '''
574
  const restartBtn = document.getElementById('restartBtn');
575
  const stopBtn = document.getElementById('stopBtn');
576
  const connectionBar = document.getElementById('connectionBar');
 
 
577
 
578
  let ws = null;
579
  let reconnectAttempts = 0;
580
  let maxReconnectAttempts = 10;
581
  let serverStartTime = null;
582
  let isServerRunning = false;
 
583
 
584
  function updateConnectionStatus(status, message) {
585
  connectionBar.className = 'connection-bar ' + status;
@@ -622,6 +872,11 @@ HTML_TEMPLATE = '''
622
  line.textContent = text;
623
  terminal.appendChild(line);
624
  terminal.scrollTop = terminal.scrollHeight;
 
 
 
 
 
625
  }
626
 
627
  function formatUptime(ms) {
@@ -727,12 +982,62 @@ HTML_TEMPLATE = '''
727
  }
728
  }
729
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730
  document.getElementById('serverAddress').textContent = window.location.hostname;
731
  addTerminalLine('Connecting to Minecraft server...', 'info');
732
  </script>
733
  </body>
734
  </html>
735
- '''
736
 
737
  @app.route('/')
738
  def index():
@@ -863,14 +1168,15 @@ sleep 5
863
  if pgrep -f "web_terminal.py" > /dev/null; then
864
  echo "✅ Web Terminal Server is running on port 7860"
865
  else
866
- echo "❌ Web Terminal failed to start"
867
  exit 1
868
  fi
869
 
870
  echo ""
871
  echo "=========================================="
872
- echo "✅ Minecraft Server with Web Terminal is LIVE!"
873
  echo "🌐 Access at: https://your-space.hf.space"
 
874
  echo "=========================================="
875
 
876
  # Keep container alive
 
77
  echo ""
78
 
79
  # ==========================================
80
+ # WEB TERMINAL SERVER (Mobile Responsive)
81
  # ==========================================
82
  cat > /app/web_terminal.py << 'PYTHON_SCRIPT'
83
  import os
 
152
 
153
  threading.Thread(target=process_commands, daemon=True).start()
154
 
155
+ HTML_TEMPLATE = """
156
  <!DOCTYPE html>
157
  <html lang="en">
158
  <head>
159
  <meta charset="UTF-8">
160
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
161
  <title>Minecraft Server - Web Console</title>
162
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
163
  <style>
164
+ * { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
165
 
166
  body {
167
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
 
169
  color: #e0e0e0;
170
  height: 100vh;
171
  overflow: hidden;
172
+ touch-action: manipulation;
173
  }
174
 
175
+ /* Mobile-first responsive design */
176
+
177
  /* Top Navigation */
178
  .top-nav {
179
  background: #252a30;
180
  border-bottom: 1px solid #363b42;
181
+ padding: 0 15px;
182
  display: flex;
183
  align-items: center;
184
  height: 50px;
185
+ position: relative;
186
+ z-index: 100;
187
  }
188
 
189
+ .nav-tabs { display: flex; gap: 0; height: 100%; overflow-x: auto; scrollbar-width: none; }
190
+ .nav-tabs::-webkit-scrollbar { display: none; }
191
 
192
  .nav-tab {
193
+ padding: 0 15px;
194
  display: flex;
195
  align-items: center;
196
+ gap: 6px;
197
  color: #9ca3af;
198
  text-decoration: none;
199
+ font-size: 13px;
200
  border-bottom: 2px solid transparent;
201
  transition: all 0.2s;
202
  cursor: pointer;
203
+ white-space: nowrap;
204
+ flex-shrink: 0;
205
  }
206
 
207
  .nav-tab:hover { color: #e0e0e0; background: rgba(255,255,255,0.05); }
 
212
  margin-left: auto;
213
  display: flex;
214
  align-items: center;
215
+ gap: 8px;
216
  }
217
 
218
  .nav-btn {
 
223
  cursor: pointer;
224
  border-radius: 4px;
225
  transition: all 0.2s;
226
+ min-width: 36px;
227
+ min-height: 36px;
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: center;
231
  }
232
 
233
  .nav-btn:hover { color: #fff; background: rgba(255,255,255,0.1); }
234
 
235
  /* Main Layout */
236
+ .main-container {
237
+ display: flex;
238
+ height: calc(100vh - 50px);
239
+ flex-direction: row;
240
+ }
241
 
242
  /* Console Area */
243
  .console-section {
 
245
  display: flex;
246
  flex-direction: column;
247
  background: #0d1117;
248
+ min-width: 0;
249
  }
250
 
251
  .console-header {
252
  background: #161b22;
253
+ padding: 12px 15px;
254
  border-bottom: 1px solid #30363d;
255
  display: flex;
256
  justify-content: space-between;
257
  align-items: center;
258
+ flex-wrap: wrap;
259
+ gap: 10px;
260
  }
261
 
262
  .server-title {
263
+ font-size: 16px;
264
  font-weight: 600;
265
  color: #f0f6fc;
266
  display: flex;
267
  align-items: center;
268
+ gap: 8px;
269
  }
270
 
271
+ .server-title i { color: #3b82f6; font-size: 18px; }
272
 
273
+ .control-buttons {
274
+ display: flex;
275
+ gap: 6px;
276
+ flex-wrap: wrap;
277
+ }
278
 
279
  .btn {
280
+ padding: 8px 14px;
281
  border: none;
282
+ border-radius: 6px;
283
+ font-size: 12px;
284
  font-weight: 500;
285
  cursor: pointer;
286
  display: flex;
287
  align-items: center;
288
+ gap: 5px;
289
  transition: all 0.2s;
290
+ min-height: 36px;
291
+ touch-action: manipulation;
292
  }
293
 
294
  .btn-primary { background: #2563eb; color: white; }
 
311
  .terminal {
312
  width: 100%;
313
  height: 100%;
314
+ padding: 12px;
315
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
316
+ font-size: 12px;
317
  line-height: 1.5;
318
  color: #e6edf3;
319
  overflow-y: auto;
320
  white-space: pre-wrap;
321
  word-wrap: break-word;
322
+ -webkit-overflow-scrolling: touch;
323
  }
324
 
325
  .terminal-line { margin: 2px 0; padding: 1px 0; }
 
332
  .command-area {
333
  background: #161b22;
334
  border-top: 1px solid #30363d;
335
+ padding: 10px 12px;
336
  display: flex;
337
+ gap: 8px;
338
  align-items: center;
339
  }
340
 
 
345
  background: #0d1117;
346
  border: 1px solid #30363d;
347
  border-radius: 6px;
348
+ padding: 0 12px;
349
  transition: border-color 0.2s;
350
+ min-height: 44px;
351
  }
352
 
353
  .command-input-wrapper:focus-within { border-color: #58a6ff; }
354
+ .command-input-wrapper i { color: #6e7681; margin-right: 8px; font-size: 14px; }
355
 
356
  #commandInput {
357
  flex: 1;
358
  background: transparent;
359
  border: none;
360
  color: #e6edf3;
361
+ padding: 10px 0;
362
  font-size: 14px;
363
  font-family: 'SFMono-Regular', Consolas, monospace;
364
  outline: none;
365
+ min-width: 0;
366
  }
367
 
368
  #commandInput::placeholder { color: #6e7681; }
 
371
  background: #238636;
372
  color: white;
373
  border: none;
374
+ padding: 12px 18px;
375
  border-radius: 6px;
376
  cursor: pointer;
377
  font-weight: 500;
378
  display: flex;
379
  align-items: center;
380
+ gap: 5px;
381
  transition: background 0.2s;
382
+ min-height: 44px;
383
+ font-size: 13px;
384
+ touch-action: manipulation;
385
  }
386
 
387
  .send-btn:hover { background: #2ea043; }
 
389
 
390
  /* Sidebar */
391
  .sidebar {
392
+ width: 280px;
393
  background: #1f2428;
394
  border-left: 1px solid #363b42;
395
+ padding: 15px;
396
  overflow-y: auto;
397
+ -webkit-overflow-scrolling: touch;
398
  }
399
 
400
  .stat-card {
401
  background: #252a30;
402
  border: 1px solid #363b42;
403
  border-radius: 8px;
404
+ padding: 12px;
405
+ margin-bottom: 10px;
406
  display: flex;
407
  align-items: center;
408
+ gap: 12px;
409
  transition: transform 0.2s, box-shadow 0.2s;
410
  }
411
 
412
  .stat-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
413
 
414
  .stat-icon {
415
+ width: 40px;
416
+ height: 40px;
417
  border-radius: 8px;
418
  display: flex;
419
  align-items: center;
420
  justify-content: center;
421
+ font-size: 18px;
422
+ flex-shrink: 0;
423
  }
424
 
425
  .stat-icon.blue { background: rgba(59, 130, 246, 0.2); color: #3b82f6; }
 
429
  .stat-icon.purple { background: rgba(168, 85, 247, 0.2); color: #a855f7; }
430
  .stat-icon.cyan { background: rgba(6, 182, 212, 0.2); color: #06b6d4; }
431
 
432
+ .stat-info { flex: 1; min-width: 0; }
433
+ .stat-label { font-size: 11px; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px; }
434
+ .stat-value { font-size: 16px; font-weight: 600; color: #f0f6fc; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
435
+ .stat-sub { font-size: 10px; color: #6b7280; margin-top: 2px; }
436
 
437
  /* Status Badge */
438
  .status-indicator {
439
  display: inline-flex;
440
  align-items: center;
441
+ gap: 5px;
442
+ padding: 4px 8px;
443
  border-radius: 20px;
444
+ font-size: 10px;
445
  font-weight: 600;
446
  text-transform: uppercase;
447
  }
 
450
  .status-offline { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
451
  .status-starting { background: rgba(234, 179, 8, 0.2); color: #eab308; }
452
 
453
+ .pulse { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: pulse 2s infinite; }
454
  @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
455
 
456
  /* Scrollbar */
457
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
458
  ::-webkit-scrollbar-track { background: #1a1d21; }
459
+ ::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 3px; }
460
  ::-webkit-scrollbar-thumb:hover { background: #6b7280; }
461
 
462
  /* Connection Status */
 
464
  position: fixed;
465
  top: 50px;
466
  left: 0;
467
+ right: 280px;
468
+ padding: 6px 15px;
469
+ font-size: 11px;
470
  font-weight: 500;
471
  display: flex;
472
  align-items: center;
473
+ gap: 6px;
474
+ z-index: 99;
475
  transition: all 0.3s;
476
  }
477
 
478
  .connection-bar.connected { background: rgba(34, 197, 94, 0.15); color: #22c55e; border-bottom: 1px solid rgba(34, 197, 94, 0.3); }
479
  .connection-bar.disconnected { background: rgba(239, 68, 68, 0.15); color: #ef4444; border-bottom: 1px solid rgba(239, 68, 68, 0.3); }
480
  .connection-bar.connecting { background: rgba(234, 179, 8, 0.15); color: #eab308; border-bottom: 1px solid rgba(234, 179, 8, 0.3); }
481
+
482
+ /* Mobile Sidebar Toggle */
483
+ .sidebar-toggle {
484
+ display: none;
485
+ position: fixed;
486
+ bottom: 20px;
487
+ right: 20px;
488
+ width: 50px;
489
+ height: 50px;
490
+ border-radius: 50%;
491
+ background: #2563eb;
492
+ color: white;
493
+ border: none;
494
+ cursor: pointer;
495
+ z-index: 200;
496
+ box-shadow: 0 4px 12px rgba(0,0,0,0.4);
497
+ font-size: 20px;
498
+ align-items: center;
499
+ justify-content: center;
500
+ }
501
+
502
+ /* Mobile Overlay */
503
+ .sidebar-overlay {
504
+ display: none;
505
+ position: fixed;
506
+ top: 0;
507
+ left: 0;
508
+ right: 0;
509
+ bottom: 0;
510
+ background: rgba(0,0,0,0.5);
511
+ z-index: 150;
512
+ }
513
+
514
+ .sidebar-overlay.active { display: block; }
515
+
516
+ /* ============================================
517
+ MOBILE RESPONSIVE BREAKPOINTS
518
+ ============================================ */
519
+
520
+ /* Tablet (768px and below) */
521
+ @media screen and (max-width: 768px) {
522
+ .sidebar {
523
+ position: fixed;
524
+ right: -100%;
525
+ top: 50px;
526
+ height: calc(100vh - 50px);
527
+ width: 280px;
528
+ z-index: 160;
529
+ transition: right 0.3s ease;
530
+ box-shadow: -4px 0 20px rgba(0,0,0,0.5);
531
+ }
532
+
533
+ .sidebar.active {
534
+ right: 0;
535
+ }
536
+
537
+ .sidebar-toggle {
538
+ display: flex;
539
+ }
540
+
541
+ .connection-bar {
542
+ right: 0;
543
+ }
544
+
545
+ .console-header {
546
+ padding: 10px 12px;
547
+ }
548
+
549
+ .server-title {
550
+ font-size: 14px;
551
+ }
552
+
553
+ .btn {
554
+ padding: 6px 10px;
555
+ font-size: 11px;
556
+ min-height: 32px;
557
+ }
558
+
559
+ .btn span {
560
+ display: none;
561
+ }
562
+
563
+ .terminal {
564
+ font-size: 11px;
565
+ padding: 10px;
566
+ }
567
+
568
+ .command-area {
569
+ padding: 8px 10px;
570
+ }
571
+
572
+ .send-btn {
573
+ padding: 10px 14px;
574
+ font-size: 12px;
575
+ }
576
+
577
+ .send-btn span {
578
+ display: none;
579
+ }
580
+ }
581
+
582
+ /* Mobile (480px and below) */
583
+ @media screen and (max-width: 480px) {
584
+ .top-nav {
585
+ padding: 0 10px;
586
+ }
587
+
588
+ .nav-tab {
589
+ padding: 0 10px;
590
+ font-size: 12px;
591
+ }
592
+
593
+ .nav-tab i {
594
+ font-size: 12px;
595
+ }
596
+
597
+ .console-header {
598
+ flex-direction: column;
599
+ align-items: flex-start;
600
+ gap: 8px;
601
+ }
602
+
603
+ .control-buttons {
604
+ width: 100%;
605
+ justify-content: flex-start;
606
+ }
607
+
608
+ .btn {
609
+ flex: 1;
610
+ justify-content: center;
611
+ padding: 8px;
612
+ }
613
+
614
+ .terminal {
615
+ font-size: 10px;
616
+ line-height: 1.4;
617
+ }
618
+
619
+ .command-input-wrapper {
620
+ min-height: 40px;
621
+ }
622
+
623
+ #commandInput {
624
+ font-size: 16px; /* Prevents zoom on iOS */
625
+ }
626
+
627
+ .send-btn {
628
+ min-height: 40px;
629
+ padding: 8px 12px;
630
+ }
631
+
632
+ .sidebar {
633
+ width: 100%;
634
+ right: -100%;
635
+ }
636
+
637
+ .stat-card {
638
+ padding: 10px;
639
+ }
640
+
641
+ .stat-icon {
642
+ width: 36px;
643
+ height: 36px;
644
+ font-size: 16px;
645
+ }
646
+
647
+ .stat-value {
648
+ font-size: 14px;
649
+ }
650
+ }
651
+
652
+ /* Landscape mobile */
653
+ @media screen and (max-height: 500px) and (orientation: landscape) {
654
+ .console-header {
655
+ padding: 8px 12px;
656
+ }
657
+
658
+ .command-area {
659
+ padding: 6px 10px;
660
+ }
661
+
662
+ .sidebar {
663
+ padding: 10px;
664
+ }
665
+
666
+ .stat-card {
667
+ padding: 8px;
668
+ margin-bottom: 6px;
669
+ }
670
+ }
671
+
672
+ /* Large screens */
673
+ @media screen and (min-width: 1400px) {
674
+ .sidebar {
675
+ width: 320px;
676
+ }
677
+
678
+ .terminal {
679
+ font-size: 13px;
680
+ }
681
+
682
+ .stat-value {
683
+ font-size: 18px;
684
+ }
685
+ }
686
  </style>
687
  </head>
688
  <body>
 
702
  </div>
703
  </nav>
704
 
705
+ <!-- Sidebar Overlay -->
706
+ <div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleSidebar()"></div>
707
+
708
  <!-- Main Container -->
709
  <div class="main-container">
710
  <!-- Console Section -->
 
724
  </div>
725
  <div class="control-buttons">
726
  <button class="btn btn-primary" id="startBtn" onclick="sendCmd('start')" disabled>
727
+ <i class="fas fa-play"></i> <span>Start</span>
728
  </button>
729
  <button class="btn btn-secondary" id="restartBtn" onclick="sendCmd('restart')" disabled>
730
+ <i class="fas fa-redo"></i> <span>Restart</span>
731
  </button>
732
  <button class="btn btn-danger" id="stopBtn" onclick="sendCmd('stop')" disabled>
733
+ <i class="fas fa-stop"></i> <span>Stop</span>
734
  </button>
735
  </div>
736
  </div>
 
745
  <input type="text" id="commandInput" placeholder="Type a command..." autocomplete="off" disabled>
746
  </div>
747
  <button class="send-btn" id="sendBtn" onclick="sendInput()" disabled>
748
+ <i class="fas fa-paper-plane"></i> <span>Send</span>
749
  </button>
750
  </div>
751
  </div>
752
 
753
  <!-- Sidebar -->
754
+ <div class="sidebar" id="sidebar">
755
  <div class="stat-card">
756
  <div class="stat-icon blue"><i class="fas fa-network-wired"></i></div>
757
  <div class="stat-info">
 
807
  </div>
808
  </div>
809
  </div>
810
+
811
+ <!-- Mobile Sidebar Toggle Button -->
812
+ <button class="sidebar-toggle" id="sidebarToggle" onclick="toggleSidebar()">
813
+ <i class="fas fa-chart-bar"></i>
814
+ </button>
815
 
816
  <script>
817
  const terminal = document.getElementById('terminal');
 
821
  const restartBtn = document.getElementById('restartBtn');
822
  const stopBtn = document.getElementById('stopBtn');
823
  const connectionBar = document.getElementById('connectionBar');
824
+ const sidebar = document.getElementById('sidebar');
825
+ const sidebarOverlay = document.getElementById('sidebarOverlay');
826
 
827
  let ws = null;
828
  let reconnectAttempts = 0;
829
  let maxReconnectAttempts = 10;
830
  let serverStartTime = null;
831
  let isServerRunning = false;
832
+ let sidebarOpen = false;
833
 
834
  function updateConnectionStatus(status, message) {
835
  connectionBar.className = 'connection-bar ' + status;
 
872
  line.textContent = text;
873
  terminal.appendChild(line);
874
  terminal.scrollTop = terminal.scrollHeight;
875
+
876
+ // Limit terminal lines for performance on mobile
877
+ while (terminal.children.length > 500) {
878
+ terminal.removeChild(terminal.firstChild);
879
+ }
880
  }
881
 
882
  function formatUptime(ms) {
 
982
  }
983
  }
984
 
985
+ function toggleSidebar() {
986
+ sidebarOpen = !sidebarOpen;
987
+ if (sidebarOpen) {
988
+ sidebar.classList.add('active');
989
+ sidebarOverlay.classList.add('active');
990
+ } else {
991
+ sidebar.classList.remove('active');
992
+ sidebarOverlay.classList.remove('active');
993
+ }
994
+ }
995
+
996
+ // Close sidebar when clicking outside on mobile
997
+ document.addEventListener('click', (e) => {
998
+ if (window.innerWidth <= 768 && sidebarOpen) {
999
+ if (!sidebar.contains(e.target) && !e.target.closest('.sidebar-toggle')) {
1000
+ toggleSidebar();
1001
+ }
1002
+ }
1003
+ });
1004
+
1005
+ // Handle orientation change
1006
+ window.addEventListener('orientationchange', () => {
1007
+ setTimeout(() => {
1008
+ terminal.scrollTop = terminal.scrollHeight;
1009
+ }, 300);
1010
+ });
1011
+
1012
+ // Handle resize
1013
+ let resizeTimer;
1014
+ window.addEventListener('resize', () => {
1015
+ clearTimeout(resizeTimer);
1016
+ resizeTimer = setTimeout(() => {
1017
+ if (window.innerWidth > 768) {
1018
+ sidebar.classList.remove('active');
1019
+ sidebarOverlay.classList.remove('active');
1020
+ sidebarOpen = false;
1021
+ }
1022
+ }, 250);
1023
+ });
1024
+
1025
+ // Prevent zoom on double tap for iOS
1026
+ let lastTouchEnd = 0;
1027
+ document.addEventListener('touchend', (e) => {
1028
+ const now = Date.now();
1029
+ if (now - lastTouchEnd <= 300) {
1030
+ e.preventDefault();
1031
+ }
1032
+ lastTouchEnd = now;
1033
+ }, false);
1034
+
1035
  document.getElementById('serverAddress').textContent = window.location.hostname;
1036
  addTerminalLine('Connecting to Minecraft server...', 'info');
1037
  </script>
1038
  </body>
1039
  </html>
1040
+ """
1041
 
1042
  @app.route('/')
1043
  def index():
 
1168
  if pgrep -f "web_terminal.py" > /dev/null; then
1169
  echo "✅ Web Terminal Server is running on port 7860"
1170
  else
1171
+ echo "❌ Web Terminal Server failed to start"
1172
  exit 1
1173
  fi
1174
 
1175
  echo ""
1176
  echo "=========================================="
1177
+ echo "✅ Minecraft Server with Mobile Responsive Web Terminal is LIVE!"
1178
  echo "🌐 Access at: https://your-space.hf.space"
1179
+ echo "📱 Mobile optimized interface enabled"
1180
  echo "=========================================="
1181
 
1182
  # Keep container alive