shell-mirror 1.5.57 → 1.5.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-mirror",
3
- "version": "1.5.57",
3
+ "version": "1.5.58",
4
4
  "description": "Access your Mac shell from any device securely. Perfect for mobile coding with Claude Code CLI, Gemini CLI, and any shell tool.",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -152,6 +152,37 @@ body {
152
152
  animation: spin 1s linear infinite;
153
153
  }
154
154
 
155
+ /* Inline Refresh Button */
156
+ .refresh-btn-inline {
157
+ background: #f8f9fa;
158
+ border: 1px solid #e9ecef;
159
+ border-radius: 50%;
160
+ color: #666;
161
+ width: 32px;
162
+ height: 32px;
163
+ cursor: pointer;
164
+ transition: all 0.2s ease;
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ font-size: 0.9rem;
169
+ }
170
+
171
+ .refresh-btn-inline:hover:not(:disabled) {
172
+ background: #e9ecef;
173
+ color: #333;
174
+ transform: scale(1.05);
175
+ }
176
+
177
+ .refresh-btn-inline.loading {
178
+ opacity: 0.7;
179
+ cursor: not-allowed;
180
+ }
181
+
182
+ .refresh-btn-inline.loading .refresh-icon {
183
+ animation: spin 1s linear infinite;
184
+ }
185
+
155
186
  .connection-status {
156
187
  font-size: 0.8rem;
157
188
  font-weight: 500;
@@ -242,6 +273,12 @@ body {
242
273
  margin-bottom: 20px;
243
274
  }
244
275
 
276
+ .card-title-section {
277
+ display: flex;
278
+ align-items: center;
279
+ gap: 12px;
280
+ }
281
+
245
282
  .card-header h2 {
246
283
  font-size: 1.3rem;
247
284
  font-weight: 600;
@@ -12,6 +12,8 @@ class ShellMirrorDashboard {
12
12
  this.refreshInterval = null;
13
13
  this.lastRefresh = null;
14
14
  this.isRefreshing = false;
15
+ this.connectionStatusDebounce = null;
16
+ this.currentConnectionStatus = null;
15
17
  this.init();
16
18
  }
17
19
 
@@ -297,16 +299,51 @@ class ShellMirrorDashboard {
297
299
  }
298
300
 
299
301
  updateConnectionStatus(status) {
302
+ // Debounce rapid status changes to prevent UI flickering
303
+ if (this.connectionStatusDebounce) {
304
+ clearTimeout(this.connectionStatusDebounce);
305
+ }
306
+
307
+ // Don't update if status is the same
308
+ if (this.currentConnectionStatus === status) {
309
+ return;
310
+ }
311
+
312
+ // For rapid disconnection/reconnection, only show status after a delay
313
+ if (status === 'disconnected' && this.currentConnectionStatus === 'connected') {
314
+ this.connectionStatusDebounce = setTimeout(() => {
315
+ this.setConnectionStatusUI(status);
316
+ }, 2000); // Wait 2 seconds before showing disconnected
317
+ return;
318
+ }
319
+
320
+ // For reconnection, show immediately but don't flicker
321
+ if (status === 'connected' && this.connectionStatusDebounce) {
322
+ clearTimeout(this.connectionStatusDebounce);
323
+ this.connectionStatusDebounce = null;
324
+ }
325
+
326
+ this.setConnectionStatusUI(status);
327
+ }
328
+
329
+ setConnectionStatusUI(status) {
330
+ this.currentConnectionStatus = status;
300
331
  const connectionStatus = document.getElementById('connection-status');
301
332
  if (connectionStatus) {
302
333
  connectionStatus.className = `connection-status ${status}`;
303
- const statusText = {
304
- connected: '🟢 Live',
305
- disconnected: '🟡 Reconnecting...',
306
- error: '🔴 Connection Error',
307
- failed: '🔴 Offline'
334
+
335
+ // Only show status when there are issues or special modes
336
+ const statusConfig = {
337
+ connected: { text: '', show: false }, // Hide when everything is working
338
+ disconnected: { text: '🟡 Reconnecting...', show: true },
339
+ error: { text: '🔴 Connection Error', show: true },
340
+ failed: { text: '🔴 Offline', show: true },
341
+ offline: { text: '📡 HTTP Only', show: true }
308
342
  };
309
- connectionStatus.textContent = statusText[status] || '❓ Unknown';
343
+
344
+ const config = statusConfig[status] || { text: '❓ Unknown', show: true };
345
+ connectionStatus.textContent = config.text;
346
+ connectionStatus.style.display = config.show ? 'inline-block' : 'none';
310
347
  }
311
348
  }
312
349
 
@@ -465,14 +502,11 @@ class ShellMirrorDashboard {
465
502
  }
466
503
 
467
504
  renderAuthenticatedDashboard() {
468
- // Update user section with refresh button and status
505
+ // Update user section - simplified without refresh button
469
506
  document.getElementById('user-section').innerHTML = `
470
507
  <div class="dashboard-controls">
471
- <span id="connection-status" class="connection-status">🟡 Connecting...</span>
508
+ <span id="connection-status" class="connection-status" style="display: none;"></span>
472
509
  <span id="refresh-status" class="refresh-status">Initializing...</span>
473
- <button id="refresh-btn" class="refresh-btn" onclick="dashboard.manualRefresh()" title="Refresh agents">
474
- <span class="refresh-icon">🔄</span>
475
- </button>
476
510
  </div>
477
511
  <div class="user-info">
478
512
  <span class="user-name">${this.user.name || this.user.email}</span>
@@ -537,8 +571,13 @@ class ShellMirrorDashboard {
537
571
  return `
538
572
  <div class="dashboard-card">
539
573
  <div class="card-header">
540
- <h2>🖥️ Active Agents</h2>
541
- <span class="agent-count">${agentCount} agent${agentCount !== 1 ? 's' : ''}</span>
574
+ <div class="card-title-section">
575
+ <h2>🖥️ Active Agents</h2>
576
+ <span class="agent-count">${agentCount} agent${agentCount !== 1 ? 's' : ''}</span>
577
+ </div>
578
+ <button id="refresh-btn" class="refresh-btn-inline" onclick="dashboard.manualRefresh()" title="Refresh agents">
579
+ <span class="refresh-icon">🔄</span>
580
+ </button>
542
581
  </div>
543
582
  <div class="card-content">
544
583
  ${agentCount > 0 ? agentsHtml : '<p class="no-data">No active agents. <a href="#" onclick="dashboard.showAgentInstructions()">Set up an agent</a></p>'}