@hmduc16031996/claude-mb-bridge 2.3.4 → 2.3.6

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/dist/index.js CHANGED
@@ -6,7 +6,7 @@ const program = new Command();
6
6
  program
7
7
  .name('claude-mobile-bridge')
8
8
  .description('Bridge Claude Code CLI to mobile via WebView')
9
- .version('2.3.3')
9
+ .version('2.3.6')
10
10
  .option('--token <token>', 'Pairing token from mobile app')
11
11
  .option('--server <url>', 'Backend server URL', 'http://127.0.0.1:3110')
12
12
  .option('--path <path>', 'Working directory', process.cwd())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hmduc16031996/claude-mb-bridge",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
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
@@ -127,6 +127,10 @@ class ClaudeBridge {
127
127
  terminalContainer: document.getElementById('terminal-container'),
128
128
  mobileKeys: document.getElementById('mobile-keys'),
129
129
  header: document.getElementById('header'),
130
+ toggleHeaderBtn: document.getElementById('toggle-header-btn'),
131
+ toggleHeaderBtnDesktop: document.getElementById('toggle-header-btn-desktop'),
132
+ expandHeaderBtn: document.getElementById('expand-header-btn'),
133
+ scrollBottomBtn: document.getElementById('scroll-bottom-btn'),
130
134
  };
131
135
  }
132
136
 
@@ -172,7 +176,16 @@ class ClaudeBridge {
172
176
  }
173
177
  });
174
178
 
175
- window.addEventListener('resize', () => this.fitAddon.fit());
179
+ window.addEventListener('resize', () => {
180
+ this.fitAddon.fit();
181
+ });
182
+
183
+ this.terminal.onScroll((e) => {
184
+ const buffer = this.terminal.buffer.active;
185
+ const isAtBottom = buffer.viewportY >= buffer.baseY;
186
+ this.elements.scrollBottomBtn.classList.toggle('hidden', isAtBottom);
187
+ });
188
+
176
189
  new TouchScrollManager(this.terminal, this.elements.terminalContainer);
177
190
  }
178
191
 
@@ -191,6 +204,35 @@ class ClaudeBridge {
191
204
  }
192
205
  });
193
206
  });
207
+
208
+ // Header Toggle
209
+ const handleToggleHeader = () => {
210
+ const isCollapsed = this.elements.header.classList.toggle('collapsed');
211
+ this.elements.expandHeaderBtn.classList.toggle('hidden', !isCollapsed);
212
+ this.elements.toggleHeaderBtn.setAttribute('aria-expanded', !isCollapsed);
213
+ this.elements.toggleHeaderBtnDesktop.setAttribute('aria-expanded', !isCollapsed);
214
+ setTimeout(() => this.fitAddon.fit(), 200);
215
+ };
216
+
217
+ this.elements.toggleHeaderBtn.addEventListener('click', handleToggleHeader);
218
+ this.elements.toggleHeaderBtnDesktop.addEventListener('click', handleToggleHeader);
219
+ this.elements.expandHeaderBtn.addEventListener('click', handleToggleHeader);
220
+
221
+ // Scroll to Bottom
222
+ this.elements.scrollBottomBtn.addEventListener('click', () => {
223
+ this.terminal.scrollToBottom();
224
+ this.elements.scrollBottomBtn.classList.add('hidden');
225
+ });
226
+
227
+ // Stubs for other buttons
228
+ ['new-session-btn', 'attach-btn', 'preview-btn', 'settings-btn'].forEach(id => {
229
+ const btn = document.getElementById(id);
230
+ if (btn) {
231
+ btn.addEventListener('click', () => {
232
+ console.log(`Button ${id} clicked (not implemented in bridge)`);
233
+ });
234
+ }
235
+ });
194
236
  }
195
237
 
196
238
  setCtrlActive(active) {
@@ -11,13 +11,38 @@
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
13
 
14
- // Check both nested (local) and flat (npm/npx) node_modules layouts
15
- const possiblePaths = [
16
- path.join(__dirname, '..', 'node_modules', 'node-pty', 'prebuilds'),
17
- path.join(__dirname, '..', '..', 'node-pty', 'prebuilds'),
18
- ];
14
+ console.log('🔧 Running postinstall to fix node-pty permissions...');
19
15
 
20
- for (const prebuildsPath of possiblePaths) {
16
+ const findNodePtyPrebuilds = () => {
17
+ // Try to find node-pty using require.resolve
18
+ try {
19
+ const ptyPath = require.resolve('node-pty/package.json');
20
+ const prebuilds = path.join(path.dirname(ptyPath), 'prebuilds');
21
+ if (fs.existsSync(prebuilds)) {
22
+ return [prebuilds];
23
+ }
24
+ } catch (e) {
25
+ // node-pty not found via require.resolve
26
+ }
27
+
28
+ // Fallback to manual path searching
29
+ const possiblePaths = [
30
+ path.join(__dirname, '..', 'node_modules', 'node-pty', 'prebuilds'),
31
+ path.join(__dirname, '..', '..', 'node-pty', 'prebuilds'),
32
+ path.join(__dirname, '..', '..', '..', 'node-pty', 'prebuilds'),
33
+ path.join(process.cwd(), 'node_modules', 'node-pty', 'prebuilds'),
34
+ ];
35
+ return possiblePaths.filter(p => fs.existsSync(p));
36
+ };
37
+
38
+ const prebuildsPaths = findNodePtyPrebuilds();
39
+
40
+ if (prebuildsPaths.length === 0) {
41
+ console.log('⚠️ node-pty prebuilds directory not found. Skipping permission fix.');
42
+ process.exit(0);
43
+ }
44
+
45
+ for (const prebuildsPath of prebuildsPaths) {
21
46
  try {
22
47
  const entries = fs.readdirSync(prebuildsPath);
23
48
 
@@ -26,14 +51,16 @@ for (const prebuildsPath of possiblePaths) {
26
51
 
27
52
  const spawnHelper = path.join(prebuildsPath, entry, 'spawn-helper');
28
53
 
29
- try {
30
- fs.chmodSync(spawnHelper, 0o755);
31
- console.log(`✅ Fixed spawn-helper permissions: ${spawnHelper}`);
32
- } catch (e) {
33
- // Ignore errors (file might not exist on some platforms)
54
+ if (fs.existsSync(spawnHelper)) {
55
+ try {
56
+ fs.chmodSync(spawnHelper, 0o755);
57
+ console.log(`✅ Fixed spawn-helper permissions: ${spawnHelper}`);
58
+ } catch (e) {
59
+ console.error(`❌ Failed to fix permissions for ${spawnHelper}: ${e.message}`);
60
+ }
34
61
  }
35
62
  }
36
63
  } catch (e) {
37
- // Directory doesn't exist, skip
64
+ console.error(`❌ Error reading directory ${prebuildsPath}: ${e.message}`);
38
65
  }
39
66
  }