@jx0/jmux 0.3.5 → 0.3.7

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": "@jx0/jmux",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "The terminal workspace for agentic development",
5
5
  "type": "module",
6
6
  "bin": {
package/src/main.ts CHANGED
@@ -12,7 +12,7 @@ import { homedir } from "os";
12
12
 
13
13
  // --- CLI commands (run and exit before TUI) ---
14
14
 
15
- const VERSION = "0.3.5";
15
+ const VERSION = "0.3.7";
16
16
 
17
17
  const HELP = `jmux — a persistent session sidebar for tmux
18
18
 
@@ -145,6 +145,7 @@ process.stdout.write("\x1b[?1049h");
145
145
  process.stdout.write("\x1b[?1000h"); // mouse button tracking
146
146
  process.stdout.write("\x1b[?1002h"); // mouse drag tracking
147
147
  process.stdout.write("\x1b[?1006h"); // SGR extended mouse mode
148
+ process.stdout.write("\x1b[?2004h"); // bracketed paste mode
148
149
  if (process.stdin.setRawMode) {
149
150
  process.stdin.setRawMode(true);
150
151
  }
@@ -251,21 +252,10 @@ async function switchSession(sessionId: string): Promise<void> {
251
252
  await control.sendCommand(
252
253
  `switch-client -c ${ptyClientName} -t '${sessionId}'`,
253
254
  );
254
- lastViewedTimestamps.set(sessionId, Math.floor(Date.now() / 1000));
255
- sidebar.setActivity(sessionId, false);
256
255
  currentSessionId = sessionId;
257
256
  sidebar.setActiveSession(sessionId);
258
257
  sidebar.scrollToActive();
259
258
  renderFrame();
260
-
261
- // Clear attention flag if set
262
- try {
263
- await control.sendCommand(
264
- `set-option -t '${sessionId}' -u @jmux-attention`,
265
- );
266
- } catch {
267
- // Option may not be set
268
- }
269
259
  } catch {
270
260
  // Session may have been killed
271
261
  }
@@ -289,12 +279,35 @@ function scheduleRender(): void {
289
279
  }, 16); // ~60fps cap
290
280
  }
291
281
 
282
+ // --- Indicator clearing on interaction ---
283
+
284
+ function clearSessionIndicators(): void {
285
+ if (!currentSessionId) return;
286
+ const id = currentSessionId;
287
+
288
+ // Only clear if there's something to clear
289
+ const needsActivityClear = sidebar.hasActivity(id);
290
+ const needsAttentionClear = sidebar.hasAttention(id);
291
+ if (!needsActivityClear && !needsAttentionClear) return;
292
+
293
+ lastViewedTimestamps.set(id, Math.floor(Date.now() / 1000));
294
+ sidebar.setActivity(id, false);
295
+ scheduleRender();
296
+
297
+ if (needsAttentionClear) {
298
+ control.sendCommand(`set-option -t '${id}' -u @jmux-attention`).catch(() => {});
299
+ }
300
+ }
301
+
292
302
  // --- Input Router ---
293
303
 
294
304
  const inputRouter = new InputRouter(
295
305
  {
296
306
  sidebarCols: SIDEBAR_WIDTH,
297
- onPtyData: (data) => pty.write(data),
307
+ onPtyData: (data) => {
308
+ pty.write(data);
309
+ clearSessionIndicators();
310
+ },
298
311
  onSidebarClick: (row) => {
299
312
  const session = sidebar.getSessionByRow(row);
300
313
  if (session) switchSession(session.id);
@@ -500,6 +513,7 @@ async function start(): Promise<void> {
500
513
 
501
514
  function cleanup(): void {
502
515
  control.close().catch(() => {});
516
+ process.stdout.write("\x1b[?2004l"); // disable bracketed paste mode
503
517
  process.stdout.write("\x1b[?1000l"); // disable mouse button tracking
504
518
  process.stdout.write("\x1b[?1002l"); // disable mouse drag tracking
505
519
  process.stdout.write("\x1b[?1006l"); // disable SGR mouse mode
package/src/sidebar.ts CHANGED
@@ -198,6 +198,15 @@ export class Sidebar {
198
198
  }
199
199
  }
200
200
 
201
+ hasActivity(sessionId: string): boolean {
202
+ return this.activitySet.has(sessionId);
203
+ }
204
+
205
+ hasAttention(sessionId: string): boolean {
206
+ const session = this.sessions.find((s) => s.id === sessionId);
207
+ return session?.attention === true;
208
+ }
209
+
201
210
  getDisplayOrderIds(): string[] {
202
211
  return this.displayOrder
203
212
  .map((idx) => this.sessions[idx]?.id)