tabminal 3.0.5 → 3.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tabminal",
3
- "version": "3.0.5",
3
+ "version": "3.0.6",
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
@@ -170,6 +170,14 @@ function isCompactWorkspaceMode() {
170
170
  return !!window.__tabminalCompactWorkspaceMode;
171
171
  }
172
172
 
173
+ function isCompactTerminalTabsMode() {
174
+ return !!window.__tabminalCompactTerminalTabsMode;
175
+ }
176
+
177
+ function isForcedTerminalWorkspaceMode() {
178
+ return isCompactWorkspaceMode() || isCompactTerminalTabsMode();
179
+ }
180
+
173
181
  function getTerminalFontSize() {
174
182
  return IS_MOBILE ? 14 : 12;
175
183
  }
@@ -286,6 +294,13 @@ if (sidebarToggle && sidebar && sidebarOverlay) {
286
294
  sidebarOverlay.classList.remove('open');
287
295
  };
288
296
 
297
+ sidebarToggle.addEventListener('pointerdown', (event) => {
298
+ if (!isCompactWorkspaceMode()) {
299
+ return;
300
+ }
301
+ event.preventDefault();
302
+ });
303
+
289
304
  sidebarToggle.addEventListener('click', () => {
290
305
  sidebar.classList.toggle('open');
291
306
  sidebarOverlay.classList.toggle('open');
@@ -711,13 +726,13 @@ class EditorManager {
711
726
  }
712
727
 
713
728
  canToggleTerminalWorkspaceMode(session = this.currentSession) {
714
- return !!session && !isCompactWorkspaceMode();
729
+ return !!session && !isForcedTerminalWorkspaceMode();
715
730
  }
716
731
 
717
732
  hasCompactWorkspaceTabs(session = this.currentSession) {
718
733
  return !!session
719
734
  && (
720
- isCompactWorkspaceMode()
735
+ isForcedTerminalWorkspaceMode()
721
736
  || this.isTerminalTabPinned(session)
722
737
  );
723
738
  }
@@ -784,7 +799,7 @@ class EditorManager {
784
799
  && this.terminalWrapper.contains(activeElement)
785
800
  );
786
801
 
787
- if (isCompactWorkspaceMode()) {
802
+ if (isForcedTerminalWorkspaceMode()) {
788
803
  session.sharedWorkspaceState.terminalDisplayMode = 'auto';
789
804
  this.updateTerminalLayoutButton();
790
805
  return;
@@ -10864,7 +10879,7 @@ window.addEventListener('tabminal:layout-modechange', () => {
10864
10879
  && terminalEl.contains(activeElement)
10865
10880
  );
10866
10881
 
10867
- if (isCompactWorkspaceMode()) {
10882
+ if (isForcedTerminalWorkspaceMode()) {
10868
10883
  if (terminalHasFocus) {
10869
10884
  session.workspaceState.activeTabKey = TERMINAL_WORKSPACE_TAB_KEY;
10870
10885
  session.saveState();
package/public/index.html CHANGED
@@ -14,44 +14,37 @@
14
14
  <link rel="preconnect" href="https://cdn.jsdelivr.net">
15
15
  <script>
16
16
  const COMPACT_WORKSPACE_MAX_WIDTH = 767;
17
- const COMPACT_WORKSPACE_MAX_LANDSCAPE_WIDTH = 950;
18
- const COMPACT_WORKSPACE_ENTER_MAX_SHORT_HEIGHT = 500;
19
- const COMPACT_WORKSPACE_EXIT_MAX_SHORT_HEIGHT = 540;
17
+ const COMPACT_TERMINAL_TAB_MAX_WIDTH = 1408;
18
+ // Temporarily disabled short-landscape fallback. Pixel Fold and
19
+ // similar devices can oscillate around the keyboard-driven viewport
20
+ // boundary, which makes compact mode flap during sidebar animation.
21
+ // const COMPACT_WORKSPACE_MAX_LANDSCAPE_WIDTH = 950;
22
+ // const COMPACT_WORKSPACE_ENTER_MAX_SHORT_HEIGHT = 500;
23
+ // const COMPACT_WORKSPACE_EXIT_MAX_SHORT_HEIGHT = 540;
20
24
  const SIDEBAR_LAYOUT_PAUSE_MS = 360;
21
25
  let layoutLoopPausedUntil = 0;
26
+ let frozenLayoutViewport = null;
27
+ let sidebarLayoutThawTimer = 0;
22
28
 
23
29
  function shouldUseCompactWorkspaceMode(
24
30
  width,
25
31
  height,
26
32
  previousCompactWorkspaceMode = false
27
33
  ) {
28
- if (width <= COMPACT_WORKSPACE_MAX_WIDTH) {
29
- return true;
30
- }
31
-
32
- const isShortLandscapeCandidate = (
33
- width > height
34
- && width <= COMPACT_WORKSPACE_MAX_LANDSCAPE_WIDTH
35
- );
36
- if (!isShortLandscapeCandidate) {
37
- return false;
38
- }
39
-
40
- const shortHeightThreshold = previousCompactWorkspaceMode
41
- ? COMPACT_WORKSPACE_EXIT_MAX_SHORT_HEIGHT
42
- : COMPACT_WORKSPACE_ENTER_MAX_SHORT_HEIGHT;
43
- return height <= shortHeightThreshold;
34
+ // Keep the extra args to preserve the old signature for possible
35
+ // re-enable of the short-landscape fallback above.
36
+ void height;
37
+ void previousCompactWorkspaceMode;
38
+ return width <= COMPACT_WORKSPACE_MAX_WIDTH;
44
39
  }
45
40
 
46
- // Mobile Layout Manager
47
- function updateLayout() {
41
+ function readLayoutViewport() {
48
42
  const vv = window.visualViewport;
49
43
  let width = window.innerWidth;
50
44
  let height = window.innerHeight;
51
45
  let offsetTop = 0;
52
46
  let offsetLeft = 0;
53
47
 
54
- // Sanity check for iPadOS PWA bug where vv.height can be negative with physical keyboard
55
48
  if (vv && vv.height > 100) {
56
49
  width = vv.width;
57
50
  height = vv.height;
@@ -59,6 +52,24 @@
59
52
  offsetLeft = vv.offsetLeft;
60
53
  }
61
54
 
55
+ return {
56
+ width,
57
+ height,
58
+ offsetTop,
59
+ offsetLeft
60
+ };
61
+ }
62
+
63
+ // Mobile Layout Manager
64
+ function updateLayout() {
65
+ const layoutViewport = frozenLayoutViewport || readLayoutViewport();
66
+ const {
67
+ width,
68
+ height,
69
+ offsetTop,
70
+ offsetLeft
71
+ } = layoutViewport;
72
+
62
73
  document.documentElement.style.setProperty('--app-width', `${width}px`);
63
74
  document.documentElement.style.setProperty('--app-height', `${height}px`);
64
75
  document.documentElement.style.setProperty('--app-top', `${offsetTop}px`);
@@ -66,12 +77,18 @@
66
77
 
67
78
  const previousCompactWorkspaceMode =
68
79
  window.__tabminalCompactWorkspaceMode;
80
+ const previousCompactTerminalTabsMode =
81
+ window.__tabminalCompactTerminalTabsMode;
69
82
  const compactWorkspaceMode = shouldUseCompactWorkspaceMode(
70
83
  width,
71
84
  height,
72
85
  previousCompactWorkspaceMode
73
86
  );
87
+ const compactTerminalTabsMode =
88
+ width <= COMPACT_TERMINAL_TAB_MAX_WIDTH;
74
89
  window.__tabminalCompactWorkspaceMode = compactWorkspaceMode;
90
+ window.__tabminalCompactTerminalTabsMode =
91
+ compactTerminalTabsMode;
75
92
 
76
93
  if (document.body) {
77
94
  window.scrollTo(0, 0);
@@ -102,12 +119,22 @@
102
119
  }
103
120
 
104
121
  if (
105
- previousCompactWorkspaceMode !== undefined
106
- && previousCompactWorkspaceMode !== compactWorkspaceMode
122
+ (
123
+ previousCompactWorkspaceMode !== undefined
124
+ && previousCompactWorkspaceMode !== compactWorkspaceMode
125
+ )
126
+ || (
127
+ previousCompactTerminalTabsMode !== undefined
128
+ && previousCompactTerminalTabsMode
129
+ !== compactTerminalTabsMode
130
+ )
107
131
  ) {
108
132
  window.dispatchEvent(
109
133
  new CustomEvent('tabminal:layout-modechange', {
110
- detail: { compactWorkspaceMode }
134
+ detail: {
135
+ compactWorkspaceMode,
136
+ compactTerminalTabsMode
137
+ }
111
138
  })
112
139
  );
113
140
  }
@@ -121,6 +148,25 @@
121
148
  );
122
149
  }
123
150
 
151
+ function freezeLayoutViewport() {
152
+ frozenLayoutViewport = readLayoutViewport();
153
+ if (sidebarLayoutThawTimer) {
154
+ clearTimeout(sidebarLayoutThawTimer);
155
+ sidebarLayoutThawTimer = 0;
156
+ }
157
+ }
158
+
159
+ function thawLayoutViewport() {
160
+ if (sidebarLayoutThawTimer) {
161
+ clearTimeout(sidebarLayoutThawTimer);
162
+ }
163
+ sidebarLayoutThawTimer = window.setTimeout(() => {
164
+ frozenLayoutViewport = null;
165
+ sidebarLayoutThawTimer = 0;
166
+ updateLayout();
167
+ }, SIDEBAR_LAYOUT_PAUSE_MS);
168
+ }
169
+
124
170
  window.__tabminalPauseLayoutLoop = pauseLayoutLoop;
125
171
 
126
172
  if (window.visualViewport) {
@@ -154,6 +200,11 @@
154
200
  }
155
201
  sidebarOpen = isOpen;
156
202
  pauseLayoutLoop();
203
+ if (isOpen) {
204
+ freezeLayoutViewport();
205
+ } else {
206
+ thawLayoutViewport();
207
+ }
157
208
  });
158
209
  observer.observe(sidebar, {
159
210
  attributes: true,