rms-devremote 3.1.0 → 3.2.0
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 +1 -1
- package/dist/server/frontend.js +85 -91
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const program = new Command();
|
|
|
4
4
|
program
|
|
5
5
|
.name('rms-devremote')
|
|
6
6
|
.description('Share your local terminal remotely with push notifications')
|
|
7
|
-
.version('2.0
|
|
7
|
+
.version('3.2.0');
|
|
8
8
|
// Helper: lazy-load a command module by path (relative to dist/)
|
|
9
9
|
async function runCommand(modulePath) {
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
package/dist/server/frontend.js
CHANGED
|
@@ -32,6 +32,8 @@ export function buildFrontendHTML() {
|
|
|
32
32
|
<span class="h-status" id="status-text">connecting</span>
|
|
33
33
|
</div>
|
|
34
34
|
<div class="h-right">
|
|
35
|
+
<button class="h-btn" id="btn-wins" title="Windows"><span id="win-label">1</span></button>
|
|
36
|
+
<button class="h-btn" id="btn-new-win" title="New window">+</button>
|
|
35
37
|
<button class="h-btn" id="btn-kb" title="Keyboard">⌨</button>
|
|
36
38
|
<button class="h-btn" id="btn-toggle" title="Toolbar">⚙</button>
|
|
37
39
|
</div>
|
|
@@ -46,12 +48,9 @@ export function buildFrontendHTML() {
|
|
|
46
48
|
<div class="info-row"><span class="info-label">Uptime</span><span class="info-value" id="info-uptime">--</span></div>
|
|
47
49
|
</div>
|
|
48
50
|
|
|
49
|
-
<!--
|
|
50
|
-
<div id="
|
|
51
|
-
<div id="
|
|
52
|
-
<div id="tabs-list"></div>
|
|
53
|
-
<button id="tab-add" title="New window">+</button>
|
|
54
|
-
</div>
|
|
51
|
+
<!-- Window selector (dropdown from header) -->
|
|
52
|
+
<div id="win-dropdown" class="hidden">
|
|
53
|
+
<div id="win-list"></div>
|
|
55
54
|
</div>
|
|
56
55
|
|
|
57
56
|
<!-- Terminal -->
|
|
@@ -133,7 +132,7 @@ const CSS = `
|
|
|
133
132
|
--muted: #888888;
|
|
134
133
|
--border: #333333;
|
|
135
134
|
--header-h: 44px;
|
|
136
|
-
--tabbar-h:
|
|
135
|
+
--tabbar-h: 0px;
|
|
137
136
|
--input-h: 48px;
|
|
138
137
|
--toolbar-h: 104px;
|
|
139
138
|
--safe-t: env(safe-area-inset-top, 0px);
|
|
@@ -209,7 +208,7 @@ body { touch-action: none; }
|
|
|
209
208
|
/* ── Info panel ──────────────────────────── */
|
|
210
209
|
#info-panel {
|
|
211
210
|
position: fixed;
|
|
212
|
-
top: calc(var(--header-h) + var(--
|
|
211
|
+
top: calc(var(--header-h) + var(--safe-t));
|
|
213
212
|
left: 0; right: 0;
|
|
214
213
|
background: var(--surface);
|
|
215
214
|
border-bottom: 2px solid var(--border);
|
|
@@ -230,76 +229,53 @@ body { touch-action: none; }
|
|
|
230
229
|
.info-value.err { color: var(--danger); }
|
|
231
230
|
.info-value.info-path { font-size: 12px; max-width: 60%; text-align: right; word-break: break-all; }
|
|
232
231
|
|
|
233
|
-
/* ──
|
|
234
|
-
#
|
|
232
|
+
/* ── Window selector dropdown ───────────── */
|
|
233
|
+
#btn-wins {
|
|
234
|
+
font-size: 14px; font-weight: 800; min-width: 36px;
|
|
235
|
+
}
|
|
236
|
+
#btn-wins.active { border-color: var(--accent); color: var(--accent); background: rgba(0,255,170,0.08); }
|
|
237
|
+
#btn-new-win { font-size: 22px; font-weight: 400; }
|
|
238
|
+
#win-dropdown {
|
|
235
239
|
position: fixed;
|
|
236
240
|
top: calc(var(--header-h) + var(--safe-t));
|
|
237
|
-
|
|
238
|
-
height: var(--tabbar-h);
|
|
241
|
+
right: 0; left: 0;
|
|
239
242
|
background: var(--surface);
|
|
240
|
-
border-bottom:
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
#tabs-scroll {
|
|
246
|
-
display: flex; align-items: center;
|
|
247
|
-
overflow-x: auto; overflow-y: hidden;
|
|
248
|
-
width: 100%; height: 100%;
|
|
249
|
-
padding: 0 calc(6px + var(--safe-l)) 0 calc(6px + var(--safe-r));
|
|
250
|
-
gap: 4px;
|
|
251
|
-
scrollbar-width: none;
|
|
252
|
-
-webkit-overflow-scrolling: touch;
|
|
253
|
-
}
|
|
254
|
-
#tabs-scroll::-webkit-scrollbar { display: none; }
|
|
255
|
-
#tabs-list {
|
|
256
|
-
display: flex; align-items: center; gap: 4px;
|
|
257
|
-
flex-shrink: 0;
|
|
243
|
+
border-bottom: 2px solid var(--border);
|
|
244
|
+
padding: 8px calc(14px + var(--safe-l)) 10px calc(14px + var(--safe-r));
|
|
245
|
+
z-index: 92;
|
|
246
|
+
animation: slideDown 0.15s ease-out;
|
|
247
|
+
display: flex; flex-direction: column; gap: 4px;
|
|
258
248
|
}
|
|
259
|
-
.
|
|
260
|
-
|
|
261
|
-
flex-
|
|
262
|
-
|
|
263
|
-
background: var(--surface2); border:
|
|
264
|
-
border-radius:
|
|
265
|
-
font-size: 12px; font-weight: 600;
|
|
266
|
-
color: var(--muted); cursor: pointer;
|
|
249
|
+
#win-dropdown.hidden { display: none !important; }
|
|
250
|
+
.win-row {
|
|
251
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
252
|
+
padding: 10px 12px;
|
|
253
|
+
background: var(--surface2); border: 2px solid var(--border);
|
|
254
|
+
border-radius: 8px; cursor: pointer;
|
|
267
255
|
-webkit-tap-highlight-color: transparent;
|
|
268
|
-
transition:
|
|
269
|
-
white-space: nowrap;
|
|
256
|
+
transition: border-color 0.12s, background 0.12s;
|
|
270
257
|
}
|
|
271
|
-
.
|
|
272
|
-
.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
258
|
+
.win-row:active { background: #222; }
|
|
259
|
+
.win-row.active { border-color: var(--accent); background: rgba(0,255,170,0.06); }
|
|
260
|
+
.win-name {
|
|
261
|
+
font-size: 14px; font-weight: 600; color: var(--text);
|
|
262
|
+
font-family: 'JetBrains Mono', monospace;
|
|
276
263
|
}
|
|
277
|
-
.
|
|
264
|
+
.win-row.active .win-name { color: var(--accent); }
|
|
265
|
+
.win-close {
|
|
266
|
+
width: 24px; height: 24px;
|
|
278
267
|
display: flex; align-items: center; justify-content: center;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
border-radius: 3px; cursor: pointer; padding: 0;
|
|
268
|
+
font-size: 16px; font-weight: 700;
|
|
269
|
+
color: var(--muted); background: none; border: none;
|
|
270
|
+
border-radius: 4px; cursor: pointer;
|
|
283
271
|
-webkit-tap-highlight-color: transparent;
|
|
284
|
-
line-height: 1;
|
|
285
272
|
}
|
|
286
|
-
.
|
|
287
|
-
#tab-add {
|
|
288
|
-
flex-shrink: 0;
|
|
289
|
-
width: 28px; height: 28px;
|
|
290
|
-
background: var(--surface2); border: 1px dashed var(--border);
|
|
291
|
-
border-radius: 6px;
|
|
292
|
-
color: var(--muted); font-size: 18px; font-weight: 400;
|
|
293
|
-
cursor: pointer; display: flex; align-items: center; justify-content: center;
|
|
294
|
-
-webkit-tap-highlight-color: transparent;
|
|
295
|
-
transition: border-color 0.12s, color 0.12s;
|
|
296
|
-
}
|
|
297
|
-
#tab-add:active { border-color: var(--accent); color: var(--accent); }
|
|
273
|
+
.win-close:active { background: rgba(255,51,85,0.3); color: var(--danger); }
|
|
298
274
|
|
|
299
275
|
/* ── Terminal ───────────────────────────── */
|
|
300
276
|
#terminal-container {
|
|
301
277
|
position: fixed;
|
|
302
|
-
top: calc(var(--header-h) + var(--
|
|
278
|
+
top: calc(var(--header-h) + var(--safe-t)); left: 0; right: 0;
|
|
303
279
|
bottom: calc(var(--input-h) + var(--toolbar-h) + var(--safe-b));
|
|
304
280
|
background: var(--bg);
|
|
305
281
|
opacity: 0; animation: fadeIn 0.3s 0.2s forwards;
|
|
@@ -441,7 +417,6 @@ body.keyboard-open #terminal-container { bottom: calc(var(--input-h) + var(--saf
|
|
|
441
417
|
@media (orientation: landscape) {
|
|
442
418
|
:root {
|
|
443
419
|
--header-h: 36px;
|
|
444
|
-
--tabbar-h: 32px;
|
|
445
420
|
--input-h: 40px;
|
|
446
421
|
--toolbar-h: 52px;
|
|
447
422
|
}
|
|
@@ -557,7 +532,7 @@ const JS = `
|
|
|
557
532
|
container.classList.add('hidden');
|
|
558
533
|
inputBar.classList.add('hidden');
|
|
559
534
|
toolbar.classList.add('hidden');
|
|
560
|
-
|
|
535
|
+
toggleWinDropdown(false);
|
|
561
536
|
disconnect.classList.remove('hidden');
|
|
562
537
|
dcTitle.textContent = title;
|
|
563
538
|
dcReason.textContent = reason;
|
|
@@ -909,48 +884,54 @@ const JS = `
|
|
|
909
884
|
navigator.serviceWorker.register('/sw.js').catch(function() {});
|
|
910
885
|
}
|
|
911
886
|
|
|
912
|
-
// ──
|
|
913
|
-
var
|
|
914
|
-
var
|
|
915
|
-
var
|
|
887
|
+
// ── Window management (header buttons + dropdown) ───────
|
|
888
|
+
var btnWins = document.getElementById('btn-wins');
|
|
889
|
+
var btnNewWin = document.getElementById('btn-new-win');
|
|
890
|
+
var winLabel = document.getElementById('win-label');
|
|
891
|
+
var winDropdown = document.getElementById('win-dropdown');
|
|
892
|
+
var winList = document.getElementById('win-list');
|
|
916
893
|
var windowsCache = [];
|
|
917
894
|
var windowsPollTimer = null;
|
|
895
|
+
var winDropdownOpen = false;
|
|
918
896
|
|
|
919
897
|
function fetchWindows() {
|
|
920
898
|
fetch('/windows', { credentials: 'same-origin' })
|
|
921
899
|
.then(function(r) { return r.json(); })
|
|
922
900
|
.then(function(wins) {
|
|
923
901
|
windowsCache = wins;
|
|
924
|
-
|
|
902
|
+
updateWinLabel(wins);
|
|
903
|
+
if (winDropdownOpen) renderWinDropdown(wins);
|
|
925
904
|
})
|
|
926
905
|
.catch(function() {});
|
|
927
906
|
}
|
|
928
907
|
|
|
929
|
-
function
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
908
|
+
function updateWinLabel(wins) {
|
|
909
|
+
if (!wins || wins.length === 0) { winLabel.textContent = '0'; return; }
|
|
910
|
+
var active = wins.find(function(w) { return w.active; });
|
|
911
|
+
winLabel.textContent = active ? active.index : wins.length;
|
|
912
|
+
}
|
|
933
913
|
|
|
934
|
-
|
|
935
|
-
|
|
914
|
+
function renderWinDropdown(wins) {
|
|
915
|
+
while (winList.firstChild) winList.removeChild(winList.firstChild);
|
|
916
|
+
if (!wins) return;
|
|
936
917
|
|
|
937
918
|
wins.forEach(function(w) {
|
|
938
|
-
var
|
|
939
|
-
|
|
919
|
+
var row = document.createElement('div');
|
|
920
|
+
row.className = 'win-row' + (w.active ? ' active' : '');
|
|
940
921
|
|
|
941
|
-
var
|
|
942
|
-
|
|
943
|
-
|
|
922
|
+
var name = document.createElement('span');
|
|
923
|
+
name.className = 'win-name';
|
|
924
|
+
name.textContent = w.index + ' : ' + (w.name || 'bash');
|
|
925
|
+
row.appendChild(name);
|
|
944
926
|
|
|
945
927
|
// Close button (only if more than 1 window)
|
|
946
928
|
if (wins.length > 1) {
|
|
947
929
|
var closeBtn = document.createElement('button');
|
|
948
|
-
closeBtn.className = '
|
|
930
|
+
closeBtn.className = 'win-close';
|
|
949
931
|
closeBtn.textContent = '\\u00d7';
|
|
950
932
|
closeBtn.setAttribute('tabindex', '-1');
|
|
951
933
|
closeBtn.addEventListener('touchstart', function(e) {
|
|
952
|
-
e.stopPropagation();
|
|
953
|
-
e.preventDefault();
|
|
934
|
+
e.stopPropagation(); e.preventDefault();
|
|
954
935
|
if (navigator.vibrate) navigator.vibrate(VIBRATE);
|
|
955
936
|
sendWsMsg({ type: 'window-close', index: w.index });
|
|
956
937
|
}, { passive: false });
|
|
@@ -959,31 +940,44 @@ const JS = `
|
|
|
959
940
|
if (navigator.vibrate) navigator.vibrate(VIBRATE);
|
|
960
941
|
sendWsMsg({ type: 'window-close', index: w.index });
|
|
961
942
|
});
|
|
962
|
-
|
|
943
|
+
row.appendChild(closeBtn);
|
|
963
944
|
}
|
|
964
945
|
|
|
965
946
|
// Switch on tap
|
|
966
|
-
|
|
947
|
+
row.addEventListener('touchstart', function(e) {
|
|
967
948
|
e.preventDefault();
|
|
968
949
|
if (navigator.vibrate) navigator.vibrate(VIBRATE);
|
|
969
950
|
sendWsMsg({ type: 'window-switch', index: w.index });
|
|
951
|
+
toggleWinDropdown(false);
|
|
970
952
|
}, { passive: false });
|
|
971
|
-
|
|
953
|
+
row.addEventListener('click', function() {
|
|
972
954
|
if (navigator.vibrate) navigator.vibrate(VIBRATE);
|
|
973
955
|
sendWsMsg({ type: 'window-switch', index: w.index });
|
|
956
|
+
toggleWinDropdown(false);
|
|
974
957
|
});
|
|
975
958
|
|
|
976
|
-
|
|
959
|
+
winList.appendChild(row);
|
|
977
960
|
});
|
|
978
961
|
}
|
|
979
962
|
|
|
963
|
+
function toggleWinDropdown(force) {
|
|
964
|
+
winDropdownOpen = force !== undefined ? force : !winDropdownOpen;
|
|
965
|
+
winDropdown.classList.toggle('hidden', !winDropdownOpen);
|
|
966
|
+
btnWins.classList.toggle('active', winDropdownOpen);
|
|
967
|
+
// Close info panel if open
|
|
968
|
+
if (winDropdownOpen && infoOpen) { infoOpen = false; infoPanel.classList.add('hidden'); }
|
|
969
|
+
if (winDropdownOpen) renderWinDropdown(windowsCache);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
btnWins.addEventListener('click', function() { toggleWinDropdown(); });
|
|
973
|
+
|
|
980
974
|
// New window button
|
|
981
|
-
|
|
975
|
+
btnNewWin.addEventListener('touchstart', function(e) {
|
|
982
976
|
e.preventDefault();
|
|
983
977
|
if (navigator.vibrate) navigator.vibrate(VIBRATE);
|
|
984
978
|
sendWsMsg({ type: 'window-create' });
|
|
985
979
|
}, { passive: false });
|
|
986
|
-
|
|
980
|
+
btnNewWin.addEventListener('click', function() {
|
|
987
981
|
if (navigator.vibrate) navigator.vibrate(VIBRATE);
|
|
988
982
|
sendWsMsg({ type: 'window-create' });
|
|
989
983
|
});
|