@hmduc16031996/claude-mb-bridge 2.5.2 → 2.5.4

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": "@hmduc16031996/claude-mb-bridge",
3
- "version": "2.5.2",
3
+ "version": "2.5.4",
4
4
  "description": "Bridge between Claude Code CLI and your mobile app via WebView",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/public/app.js CHANGED
@@ -1688,7 +1688,6 @@ class ClaudeRemote {
1688
1688
  }
1689
1689
  }
1690
1690
 
1691
- // Mobile keys methods
1692
1691
  initMobileKeys() {
1693
1692
  // Only init on touch devices
1694
1693
  if (window.matchMedia('(pointer: fine)').matches) return;
@@ -1723,54 +1722,45 @@ class ClaudeRemote {
1723
1722
  });
1724
1723
  }, { passive: true });
1725
1724
 
1726
- // Detect keyboard visibility using visualViewport API
1725
+ // Always show in mobile flex flow
1726
+ this.elements.mainScreen.classList.add('mobile-keys-visible');
1727
+
1728
+ // Handle initial sizing
1727
1729
  if (window.visualViewport) {
1728
1730
  window.visualViewport.addEventListener('resize', () => this.onViewportChange());
1729
1731
  window.visualViewport.addEventListener('scroll', () => this.onViewportChange());
1732
+ this.onViewportChange();
1730
1733
  }
1731
1734
  }
1732
1735
 
1733
1736
  onViewportChange() {
1734
- const viewport = window.visualViewport;
1735
- const heightDiff = window.innerHeight - viewport.height;
1736
-
1737
- // If viewport is significantly smaller than window, keyboard is likely open
1738
- // Using 150px threshold to account for keyboard
1739
- const keyboardOpen = heightDiff > 150;
1740
-
1741
- if (keyboardOpen && this.elements.mainScreen.classList.contains('active')) {
1742
- // Position toolbar just above the keyboard
1743
- // Account for visual viewport offset when page is scrolled
1744
- const keyboardHeight = window.innerHeight - viewport.height - viewport.offsetTop;
1745
- this.elements.mobileKeys.style.bottom = `${Math.max(0, keyboardHeight)}px`;
1746
- this.showMobileKeys();
1747
- } else {
1748
- this.hideMobileKeys();
1737
+ if (!window.visualViewport) return;
1738
+
1739
+ // Adjust app height to match visual viewport (the actual visible area above the keyboard)
1740
+ const viewportHeight = window.visualViewport.height;
1741
+ const bodyHeight = window.innerHeight;
1742
+
1743
+ // On some mobile browsers, setting 100% isn't enough when keyboard is open
1744
+ // We explicitly set the app height to the visual viewport height
1745
+ const app = document.getElementById('app');
1746
+ if (app) {
1747
+ app.style.height = `${viewportHeight}px`;
1749
1748
  }
1750
- }
1751
1749
 
1752
- showMobileKeys() {
1753
- this.elements.mobileKeys.classList.remove('hidden');
1754
- this.elements.mobileKeys.classList.add('visible');
1755
- this.elements.mainScreen.classList.add('mobile-keys-visible');
1750
+ // Recalculate terminal size for the new container height
1756
1751
  this.fitTerminal();
1757
- }
1758
1752
 
1759
- hideMobileKeys() {
1760
- this.elements.mobileKeys.classList.remove('visible');
1761
- this.elements.mainScreen.classList.remove('mobile-keys-visible');
1762
- // Reset modifier states when hiding
1763
- this.setCtrlActive(false);
1764
- this.setShiftActive(false);
1765
- this.fitTerminal();
1766
- // Hide after animation
1767
- setTimeout(() => {
1768
- if (!this.elements.mobileKeys.classList.contains('visible')) {
1769
- this.elements.mobileKeys.classList.add('hidden');
1770
- }
1771
- }, 300);
1753
+ // Ensure terminal scrolled to bottom so cursor is visible above keyboard
1754
+ // Only if the current session is terminal-based
1755
+ if (this.currentSessionId && this.terminal) {
1756
+ this.terminal.scrollToBottom();
1757
+ }
1758
+
1759
+ // Log for debugging visibility if needed
1760
+ // console.log(`Viewport height: ${viewportHeight}, Body height: ${bodyHeight}`);
1772
1761
  }
1773
1762
 
1763
+
1774
1764
  handleMobileKey(key) {
1775
1765
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN || !this.currentSessionId) return;
1776
1766
 
@@ -1790,12 +1780,18 @@ class ClaudeRemote {
1790
1780
  case 'slash':
1791
1781
  this.ws.send('/');
1792
1782
  break;
1783
+ case 'left':
1784
+ this.ws.send('\x1b[D'); // Arrow left
1785
+ break;
1793
1786
  case 'up':
1794
1787
  this.ws.send('\x1b[A'); // Arrow up
1795
1788
  break;
1796
1789
  case 'down':
1797
1790
  this.ws.send('\x1b[B'); // Arrow down
1798
1791
  break;
1792
+ case 'right':
1793
+ this.ws.send('\x1b[C'); // Arrow right
1794
+ break;
1799
1795
  }
1800
1796
 
1801
1797
  // Clear modifiers after sending a key (except when toggling modifiers)
package/public/index.html CHANGED
@@ -130,6 +130,19 @@
130
130
  </div>
131
131
  </header>
132
132
 
133
+ <!-- Mobile Control Keys Toolbar (visible on mobile only) -->
134
+ <div id="mobile-keys" class="mobile-keys" role="toolbar" aria-label="Control keys">
135
+ <button type="button" class="mobile-key" data-key="escape" aria-label="Escape">Esc</button>
136
+ <button type="button" class="mobile-key mobile-key-modifier" data-key="ctrl" aria-label="Control modifier" aria-pressed="false">Ctrl</button>
137
+ <button type="button" class="mobile-key mobile-key-modifier" data-key="shift" aria-label="Shift modifier" aria-pressed="false">Shift</button>
138
+ <button type="button" class="mobile-key" data-key="tab" aria-label="Tab">Tab</button>
139
+ <button type="button" class="mobile-key" data-key="slash" aria-label="Slash">/</button>
140
+ <button type="button" class="mobile-key" data-key="left" aria-label="Arrow left">←</button>
141
+ <button type="button" class="mobile-key" data-key="up" aria-label="Arrow up">↑</button>
142
+ <button type="button" class="mobile-key" data-key="down" aria-label="Arrow down">↓</button>
143
+ <button type="button" class="mobile-key" data-key="right" aria-label="Arrow right">→</button>
144
+ </div>
145
+
133
146
  <!-- Terminal Container -->
134
147
  <div id="terminal-container" role="application" aria-label="Terminal"></div>
135
148
 
@@ -140,16 +153,6 @@
140
153
  </svg>
141
154
  </button>
142
155
 
143
- <!-- Mobile Control Keys Toolbar (visible when keyboard is open on mobile) -->
144
- <div id="mobile-keys" class="mobile-keys hidden" role="toolbar" aria-label="Control keys">
145
- <button type="button" class="mobile-key" data-key="escape" aria-label="Escape">Esc</button>
146
- <button type="button" class="mobile-key mobile-key-modifier" data-key="ctrl" aria-label="Control modifier" aria-pressed="false">Ctrl</button>
147
- <button type="button" class="mobile-key mobile-key-modifier" data-key="shift" aria-label="Shift modifier" aria-pressed="false">Shift</button>
148
- <button type="button" class="mobile-key" data-key="tab" aria-label="Tab">Tab</button>
149
- <button type="button" class="mobile-key" data-key="slash" aria-label="Slash">/</button>
150
- <button type="button" class="mobile-key" data-key="up" aria-label="Arrow up">↑</button>
151
- <button type="button" class="mobile-key" data-key="down" aria-label="Arrow down">↓</button>
152
- </div>
153
156
 
154
157
  <!-- Floating expand button (visible when header collapsed) -->
155
158
  <button id="expand-header-btn" class="btn-icon floating-btn hidden" title="Show header" aria-label="Show header">
package/public/styles.css CHANGED
@@ -63,11 +63,12 @@ body {
63
63
 
64
64
  #app {
65
65
  width: 100%;
66
- height: 100%;
66
+ height: 100vh; /* Primary height */
67
67
  display: flex;
68
68
  flex-direction: column;
69
69
  position: relative;
70
70
  z-index: 1;
71
+ overflow: hidden;
71
72
  }
72
73
 
73
74
  /* ===== SCREENS ===== */
@@ -1443,36 +1444,28 @@ kbd {
1443
1444
  /* CRITICAL: z-index must be higher than touch-scroll-overlay (9999) to receive taps.
1444
1445
  The overlay doesn't create a stacking context, so its 9999 z-index competes directly. */
1445
1446
  .mobile-keys {
1446
- position: fixed;
1447
- left: 0;
1448
- right: 0;
1449
1447
  display: flex;
1450
1448
  justify-content: center;
1451
- gap: 0.5rem;
1452
- padding: 0.5rem;
1449
+ gap: 0.25rem;
1450
+ padding: 0.375rem 0.5rem;
1453
1451
  background: var(--bg-primary);
1454
- border-top: 1px solid var(--border);
1455
- z-index: 10000;
1456
- opacity: 0;
1457
- pointer-events: none;
1452
+ border-bottom: 1px solid var(--border);
1453
+ z-index: 5;
1458
1454
  transition: opacity var(--transition);
1459
- /* bottom is set dynamically by JS */
1455
+ flex-shrink: 0;
1460
1456
  }
1461
1457
 
1462
- .mobile-keys.visible {
1463
- opacity: 1;
1464
- pointer-events: auto;
1465
- }
1466
1458
 
1467
1459
  .mobile-key {
1460
+ flex: 1;
1461
+ min-width: 0;
1468
1462
  display: inline-flex;
1469
1463
  align-items: center;
1470
1464
  justify-content: center;
1471
- min-width: 48px;
1472
1465
  height: 40px;
1473
- padding: 0 0.75rem;
1466
+ padding: 0 0.25rem;
1474
1467
  font-family: var(--font-mono);
1475
- font-size: 0.8125rem;
1468
+ font-size: 0.75rem;
1476
1469
  background: var(--bg-surface);
1477
1470
  color: var(--text-secondary);
1478
1471
  border: 1px solid var(--border);
@@ -1502,15 +1495,9 @@ kbd {
1502
1495
  }
1503
1496
  }
1504
1497
 
1505
- /* Adjust terminal container when toolbar is visible */
1506
- .mobile-keys.visible + .floating-btn,
1507
- .mobile-keys.visible ~ .floating-btn {
1508
- bottom: calc(56px + max(0.5rem, env(safe-area-inset-bottom)));
1509
- }
1510
-
1511
- /* When mobile keys are visible, add padding to terminal */
1512
- #main-screen.mobile-keys-visible #terminal-container {
1513
- padding-bottom: calc(56px + env(safe-area-inset-bottom));
1498
+ /* Layout adjustments when toolbar is visible (now part of flex flow) */
1499
+ .mobile-keys + #terminal-container {
1500
+ border-top: none; /* Already have border-bottom on keys */
1514
1501
  }
1515
1502
 
1516
1503
  /* ===== SCROLL TO BOTTOM BUTTON ===== */