@jx0/jmux 0.3.6 → 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.6",
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.6";
15
+ const VERSION = "0.3.7";
16
16
 
17
17
  const HELP = `jmux — a persistent session sidebar for tmux
18
18
 
@@ -252,21 +252,10 @@ async function switchSession(sessionId: string): Promise<void> {
252
252
  await control.sendCommand(
253
253
  `switch-client -c ${ptyClientName} -t '${sessionId}'`,
254
254
  );
255
- lastViewedTimestamps.set(sessionId, Math.floor(Date.now() / 1000));
256
- sidebar.setActivity(sessionId, false);
257
255
  currentSessionId = sessionId;
258
256
  sidebar.setActiveSession(sessionId);
259
257
  sidebar.scrollToActive();
260
258
  renderFrame();
261
-
262
- // Clear attention flag if set
263
- try {
264
- await control.sendCommand(
265
- `set-option -t '${sessionId}' -u @jmux-attention`,
266
- );
267
- } catch {
268
- // Option may not be set
269
- }
270
259
  } catch {
271
260
  // Session may have been killed
272
261
  }
@@ -290,12 +279,35 @@ function scheduleRender(): void {
290
279
  }, 16); // ~60fps cap
291
280
  }
292
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
+
293
302
  // --- Input Router ---
294
303
 
295
304
  const inputRouter = new InputRouter(
296
305
  {
297
306
  sidebarCols: SIDEBAR_WIDTH,
298
- onPtyData: (data) => pty.write(data),
307
+ onPtyData: (data) => {
308
+ pty.write(data);
309
+ clearSessionIndicators();
310
+ },
299
311
  onSidebarClick: (row) => {
300
312
  const session = sidebar.getSessionByRow(row);
301
313
  if (session) switchSession(session.id);
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)