tabminal 3.0.6 → 3.0.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": "tabminal",
3
- "version": "3.0.6",
3
+ "version": "3.0.7",
4
4
  "description": "Tab(ter)minal, a Cloud-Native terminal and ACP agent workspace for desktop, tablet, and phone.",
5
5
  "type": "module",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -4994,7 +4994,10 @@ class Session {
4994
4994
  this.runningExecutionId = '';
4995
4995
  this.runningCommand = '';
4996
4996
 
4997
- if (!isTerminalViewVisible(this)) {
4997
+ if (
4998
+ state.activeSessionKey !== this.key
4999
+ && !isAgentManagedSession(this)
5000
+ ) {
4998
5001
  this.needsAttention = true;
4999
5002
  if (this.lastNotifiedExecutionId !== executionId) {
5000
5003
  this.lastNotifiedExecutionId = executionId;
package/public/index.html CHANGED
@@ -85,7 +85,7 @@
85
85
  previousCompactWorkspaceMode
86
86
  );
87
87
  const compactTerminalTabsMode =
88
- width <= COMPACT_TERMINAL_TAB_MAX_WIDTH;
88
+ width < COMPACT_TERMINAL_TAB_MAX_WIDTH;
89
89
  window.__tabminalCompactWorkspaceMode = compactWorkspaceMode;
90
90
  window.__tabminalCompactTerminalTabsMode =
91
91
  compactTerminalTabsMode;
@@ -6,6 +6,62 @@ export class NotificationManager {
6
6
  }
7
7
  }
8
8
 
9
+ // BEGIN temporary iOS web-app notification dedupe workaround
10
+ static RECENT_NOTIFICATION_KEY = 'tabminal_recent_notifications';
11
+
12
+ static RECENT_NOTIFICATION_LIMIT = 10;
13
+
14
+ static RECENT_NOTIFICATION_TTL_MS = 30_000;
15
+
16
+ _loadRecentNotifications() {
17
+ try {
18
+ const raw = localStorage.getItem(
19
+ NotificationManager.RECENT_NOTIFICATION_KEY
20
+ );
21
+ if (!raw) return [];
22
+ const parsed = JSON.parse(raw);
23
+ return Array.isArray(parsed) ? parsed : [];
24
+ } catch {
25
+ return [];
26
+ }
27
+ }
28
+
29
+ _storeRecentNotifications(entries) {
30
+ try {
31
+ localStorage.setItem(
32
+ NotificationManager.RECENT_NOTIFICATION_KEY,
33
+ JSON.stringify(entries)
34
+ );
35
+ } catch {
36
+ // Ignore localStorage failures.
37
+ }
38
+ }
39
+
40
+ _shouldSuppressRecentNotification(title, body) {
41
+ const now = Date.now();
42
+ const fingerprint = `${title}\n${body}`;
43
+ const recent = this._loadRecentNotifications().filter((entry) => (
44
+ entry
45
+ && typeof entry.fingerprint === 'string'
46
+ && Number.isFinite(entry.at)
47
+ && (now - entry.at) < NotificationManager.RECENT_NOTIFICATION_TTL_MS
48
+ ));
49
+
50
+ if (recent.some((entry) => entry.fingerprint === fingerprint)) {
51
+ this._storeRecentNotifications(
52
+ recent.slice(-NotificationManager.RECENT_NOTIFICATION_LIMIT)
53
+ );
54
+ return true;
55
+ }
56
+
57
+ recent.push({ fingerprint, at: now });
58
+ this._storeRecentNotifications(
59
+ recent.slice(-NotificationManager.RECENT_NOTIFICATION_LIMIT)
60
+ );
61
+ return false;
62
+ }
63
+ // END temporary iOS web-app notification dedupe workaround
64
+
9
65
  requestPermission() {
10
66
  if (!('Notification' in window)) return;
11
67
  if (Notification.permission !== 'granted' && Notification.permission !== 'denied') {
@@ -20,6 +76,9 @@ export class NotificationManager {
20
76
 
21
77
  // Check permission status directly
22
78
  if (Notification.permission === 'granted') {
79
+ if (this._shouldSuppressRecentNotification(title, body)) {
80
+ return true;
81
+ }
23
82
  try {
24
83
  new Notification(title, {
25
84
  body: body,