koneck 2.59.0 → 2.60.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/web/ui-client.d.ts.map +1 -1
- package/dist/web/ui-client.js +191 -13
- package/dist/web/ui-client.js.map +1 -1
- package/dist/web/ui-css.d.ts.map +1 -1
- package/dist/web/ui-css.js +2 -0
- package/dist/web/ui-css.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +10 -0
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-client.d.ts","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"ui-client.d.ts","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAizIrC"}
|
package/dist/web/ui-client.js
CHANGED
|
@@ -2703,7 +2703,9 @@ function newPane() {
|
|
|
2703
2703
|
/** Where this command's output begins, so a catch-up can replace exactly that. */
|
|
2704
2704
|
outputStart: 0,
|
|
2705
2705
|
/** How many output lines have arrived on the stream, for the same reason. */
|
|
2706
|
-
received: 0
|
|
2706
|
+
received: 0,
|
|
2707
|
+
/** Lines waiting for the next frame, so output faster than the screen costs nothing. */
|
|
2708
|
+
queue: [], flushing: false };
|
|
2707
2709
|
}
|
|
2708
2710
|
|
|
2709
2711
|
/** The pane a job's output belongs to, or null when nothing here started it. */
|
|
@@ -2764,24 +2766,104 @@ function markActivePane() {
|
|
|
2764
2766
|
});
|
|
2765
2767
|
}
|
|
2766
2768
|
|
|
2767
|
-
/**
|
|
2769
|
+
/** Whether the reader is watching the tail, or has scrolled up to look at something. */
|
|
2770
|
+
function atTail(pane) {
|
|
2771
|
+
return pane.el.scroll.scrollHeight - pane.el.scroll.scrollTop
|
|
2772
|
+
- pane.el.scroll.clientHeight < 60;
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2775
|
+
/**
|
|
2776
|
+
* Everything this pane has printed, rebuilt from scratch.
|
|
2777
|
+
*
|
|
2778
|
+
* For the cases where the whole buffer really did change — a fresh pane, a catch-up read, a clear.
|
|
2779
|
+
* A single new line does not come through here; see appendLine for why that matters.
|
|
2780
|
+
*/
|
|
2768
2781
|
function paintPane(index) {
|
|
2769
2782
|
const pane = term.panes[index];
|
|
2770
2783
|
if (!pane || !pane.el) return;
|
|
2771
|
-
const
|
|
2772
|
-
|
|
2773
|
-
pane.el.body.
|
|
2784
|
+
const wasAtTail = atTail(pane);
|
|
2785
|
+
pane.el.body.innerHTML = '';
|
|
2786
|
+
for (const line of pane.lines) pane.el.body.appendChild(lineNode(line));
|
|
2774
2787
|
pane.el.stop.hidden = !pane.running;
|
|
2775
|
-
if (
|
|
2788
|
+
if (wasAtTail) pane.el.scroll.scrollTop = pane.el.scroll.scrollHeight;
|
|
2776
2789
|
}
|
|
2777
2790
|
|
|
2791
|
+
/** One line of output, as its own element so it can be added without touching the others. */
|
|
2792
|
+
function lineNode(line) {
|
|
2793
|
+
const node = document.createElement('span');
|
|
2794
|
+
node.className = 'tl';
|
|
2795
|
+
node.innerHTML = ansiToHtml(line);
|
|
2796
|
+
return node;
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
/** Lines a pane keeps. A dev server left running overnight must not become the document. */
|
|
2800
|
+
const TERM_SCROLLBACK = 4000;
|
|
2801
|
+
|
|
2802
|
+
/*
|
|
2803
|
+
* Lines land in the document once a frame, however fast they arrive.
|
|
2804
|
+
*
|
|
2805
|
+
* Two wrong answers came before this one, and both were measured on the same two thousand lines.
|
|
2806
|
+
*
|
|
2807
|
+
* Rebuilding the whole scrollback per line — joining the buffer, reparsing it, assigning innerHTML
|
|
2808
|
+
* — took 929ms. Appending one element per line instead took 6831ms: seven times *worse*, because
|
|
2809
|
+
* deciding whether to auto-scroll reads scrollHeight, and reading layout after every write forces a
|
|
2810
|
+
* synchronous reflow. Two thousand forced reflows cost far more than two thousand innerHTML writes,
|
|
2811
|
+
* which the browser is free to batch because nothing in between asks it a question about layout.
|
|
2812
|
+
*
|
|
2813
|
+
* So the fix is not a cheaper write, it is fewer layout reads. Lines queue and go in together on the
|
|
2814
|
+
* next animation frame: one fragment appended, one measurement taken, one scroll set, at most sixty
|
|
2815
|
+
* times a second no matter how loud the command is. Output faster than the screen can show it stops
|
|
2816
|
+
* costing anything extra, which is what smooth means here.
|
|
2817
|
+
*/
|
|
2778
2818
|
function pushPane(index, line, redraw) {
|
|
2779
2819
|
const pane = term.panes[index];
|
|
2780
2820
|
if (!pane) return;
|
|
2781
2821
|
if (redraw && pane.lines.length > 0) pane.lines[pane.lines.length - 1] = line;
|
|
2782
2822
|
else pane.lines.push(line);
|
|
2783
|
-
while (pane.lines.length >
|
|
2784
|
-
|
|
2823
|
+
while (pane.lines.length > TERM_SCROLLBACK) pane.lines.shift();
|
|
2824
|
+
if (!pane.el) return;
|
|
2825
|
+
pane.queue.push({ line: line, redraw: redraw === true });
|
|
2826
|
+
scheduleFlush(index);
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
function scheduleFlush(index) {
|
|
2830
|
+
const pane = term.panes[index];
|
|
2831
|
+
if (!pane || pane.flushing) return;
|
|
2832
|
+
pane.flushing = true;
|
|
2833
|
+
requestAnimationFrame(() => flushPane(index));
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
function flushPane(index) {
|
|
2837
|
+
const pane = term.panes[index];
|
|
2838
|
+
if (!pane) return;
|
|
2839
|
+
pane.flushing = false;
|
|
2840
|
+
if (!pane.el || pane.queue.length === 0) return;
|
|
2841
|
+
|
|
2842
|
+
// The one layout read of the frame, taken before anything is written.
|
|
2843
|
+
const wasAtTail = atTail(pane);
|
|
2844
|
+
const queued = pane.queue;
|
|
2845
|
+
pane.queue = [];
|
|
2846
|
+
|
|
2847
|
+
const batch = document.createDocumentFragment();
|
|
2848
|
+
for (const item of queued) {
|
|
2849
|
+
if (item.redraw) {
|
|
2850
|
+
// A progress bar rewriting its own line. If the batch already holds it, replace within the
|
|
2851
|
+
// batch; otherwise the last line already in the document is the one being redrawn.
|
|
2852
|
+
if (batch.lastChild) batch.replaceChild(lineNode(item.line), batch.lastChild);
|
|
2853
|
+
else if (pane.el.body.lastChild) {
|
|
2854
|
+
pane.el.body.replaceChild(lineNode(item.line), pane.el.body.lastChild);
|
|
2855
|
+
} else batch.appendChild(lineNode(item.line));
|
|
2856
|
+
continue;
|
|
2857
|
+
}
|
|
2858
|
+
batch.appendChild(lineNode(item.line));
|
|
2859
|
+
}
|
|
2860
|
+
pane.el.body.appendChild(batch);
|
|
2861
|
+
|
|
2862
|
+
while (pane.el.body.childNodes.length > TERM_SCROLLBACK) {
|
|
2863
|
+
pane.el.body.removeChild(pane.el.body.firstChild);
|
|
2864
|
+
}
|
|
2865
|
+
pane.el.stop.hidden = !pane.running;
|
|
2866
|
+
if (wasAtTail) pane.el.scroll.scrollTop = pane.el.scroll.scrollHeight;
|
|
2785
2867
|
}
|
|
2786
2868
|
|
|
2787
2869
|
async function paneKey(ev, index) {
|
|
@@ -2912,7 +2994,24 @@ function watchTerminal() {
|
|
|
2912
2994
|
source.onerror = () => { /* the browser reconnects on its own */ };
|
|
2913
2995
|
}
|
|
2914
2996
|
|
|
2915
|
-
|
|
2997
|
+
/*
|
|
2998
|
+
* Font size and backdrop, applied to every pane at once.
|
|
2999
|
+
*
|
|
3000
|
+
* The picture is either the one KONECK ships with or one of yours, and yours is kept in this
|
|
3001
|
+
* browser's own storage rather than on the machine: it is a preference about how your terminal
|
|
3002
|
+
* looks, not something the server needs to know, and it should not travel anywhere or appear in
|
|
3003
|
+
* anybody else's session.
|
|
3004
|
+
*/
|
|
3005
|
+
const OWN_BACKDROP_KEY = 'koneck.terminal.backdrop';
|
|
3006
|
+
|
|
3007
|
+
function backdropUrl() {
|
|
3008
|
+
let own = null;
|
|
3009
|
+
try { own = localStorage.getItem(OWN_BACKDROP_KEY); } catch (e) { own = null; }
|
|
3010
|
+
if (own) return own;
|
|
3011
|
+
return '/api/terminal/background'
|
|
3012
|
+
+ (state.token ? '?token=' + encodeURIComponent(state.token) : '');
|
|
3013
|
+
}
|
|
3014
|
+
|
|
2916
3015
|
function applyTerminalLook() {
|
|
2917
3016
|
const host = $('termpanes');
|
|
2918
3017
|
host.style.setProperty('--term-font', term.fontPx + 'px');
|
|
@@ -2920,11 +3019,66 @@ function applyTerminalLook() {
|
|
|
2920
3019
|
const strength = Number($('tbgop').value) / 100;
|
|
2921
3020
|
host.classList.toggle('backdrop', on);
|
|
2922
3021
|
host.style.setProperty('--term-bg-strength', on ? String(strength) : '0');
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
3022
|
+
host.style.setProperty('--term-bg-image', 'url("' + backdropUrl() + '")');
|
|
3023
|
+
let own = null;
|
|
3024
|
+
try { own = localStorage.getItem(OWN_BACKDROP_KEY); } catch (e) { own = null; }
|
|
3025
|
+
// The way back only exists when there is something to go back from.
|
|
3026
|
+
$('tbgreset').hidden = !own;
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
$('tbgpick').onclick = () => { $('tbgfile').click(); };
|
|
3030
|
+
|
|
3031
|
+
$('tbgreset').onclick = () => {
|
|
3032
|
+
try { localStorage.removeItem(OWN_BACKDROP_KEY); } catch (e) { /* nothing stored */ }
|
|
3033
|
+
applyTerminalLook();
|
|
3034
|
+
};
|
|
3035
|
+
|
|
3036
|
+
$('tbgfile').onchange = async () => {
|
|
3037
|
+
const file = $('tbgfile').files && $('tbgfile').files[0];
|
|
3038
|
+
$('tbgfile').value = '';
|
|
3039
|
+
if (!file) return;
|
|
3040
|
+
let stored;
|
|
3041
|
+
try { stored = await shrinkForBackdrop(file); }
|
|
3042
|
+
catch (e) { $('tbgimg').title = 'That image could not be read.'; return; }
|
|
3043
|
+
try { localStorage.setItem(OWN_BACKDROP_KEY, stored); }
|
|
3044
|
+
catch (e) {
|
|
3045
|
+
// Storage is small and a photograph is not. Said rather than failed silently.
|
|
3046
|
+
$('tbgimg').title = 'That image is too large to keep in this browser.';
|
|
3047
|
+
return;
|
|
2927
3048
|
}
|
|
3049
|
+
$('tbgimg').checked = true;
|
|
3050
|
+
applyTerminalLook();
|
|
3051
|
+
};
|
|
3052
|
+
|
|
3053
|
+
/*
|
|
3054
|
+
* A picture cut down to something a browser will keep.
|
|
3055
|
+
*
|
|
3056
|
+
* A phone photograph is several megabytes and local storage is a few in total, so storing one
|
|
3057
|
+
* whole would fail — and the panes are at most a screen wide, so the pixels beyond that were never
|
|
3058
|
+
* going to be seen. Drawn once at a sane width and re-encoded as a photograph, which is what it is.
|
|
3059
|
+
*/
|
|
3060
|
+
function shrinkForBackdrop(file) {
|
|
3061
|
+
return new Promise((resolve, reject) => {
|
|
3062
|
+
const reader = new FileReader();
|
|
3063
|
+
reader.onerror = () => reject(new Error('unreadable'));
|
|
3064
|
+
reader.onload = () => {
|
|
3065
|
+
const img = new Image();
|
|
3066
|
+
img.onerror = () => reject(new Error('not an image'));
|
|
3067
|
+
img.onload = () => {
|
|
3068
|
+
const maxWide = 1920;
|
|
3069
|
+
const scale = Math.min(1, maxWide / (img.naturalWidth || maxWide));
|
|
3070
|
+
const canvas = document.createElement('canvas');
|
|
3071
|
+
canvas.width = Math.max(1, Math.round(img.naturalWidth * scale));
|
|
3072
|
+
canvas.height = Math.max(1, Math.round(img.naturalHeight * scale));
|
|
3073
|
+
const ctx = canvas.getContext('2d');
|
|
3074
|
+
if (!ctx) { reject(new Error('no canvas')); return; }
|
|
3075
|
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
3076
|
+
resolve(canvas.toDataURL('image/jpeg', 0.82));
|
|
3077
|
+
};
|
|
3078
|
+
img.src = String(reader.result);
|
|
3079
|
+
};
|
|
3080
|
+
reader.readAsDataURL(file);
|
|
3081
|
+
});
|
|
2928
3082
|
}
|
|
2929
3083
|
|
|
2930
3084
|
function startPaneDrag(ev, dividerIndex) {
|
|
@@ -3002,6 +3156,11 @@ const preview = { shot: null, width: 0 };
|
|
|
3002
3156
|
*/
|
|
3003
3157
|
const typing = { pending: '', timer: null };
|
|
3004
3158
|
|
|
3159
|
+
/** Wheel movement waiting to be sent, so a gesture is one request rather than fifty. */
|
|
3160
|
+
const scrolling = { by: 0, timer: null };
|
|
3161
|
+
/** Long enough to gather a flick of the wheel, short enough that the page keeps up with it. */
|
|
3162
|
+
const SCROLL_BATCH_MS = 70;
|
|
3163
|
+
|
|
3005
3164
|
/** Keys the page must be told about individually, with what they are called on the wire. */
|
|
3006
3165
|
const SPECIAL_KEYS = {
|
|
3007
3166
|
Enter: 'Enter', Tab: 'Tab', Backspace: 'Backspace', Escape: 'Escape',
|
|
@@ -3099,6 +3258,25 @@ function drawPreview(data) {
|
|
|
3099
3258
|
img.tabIndex = 0;
|
|
3100
3259
|
img.onkeydown = (ev) => { void pageKey(ev); };
|
|
3101
3260
|
img.onblur = () => { void flushTyping(); };
|
|
3261
|
+
/*
|
|
3262
|
+
* The wheel scrolls the page, not the panel around it.
|
|
3263
|
+
*
|
|
3264
|
+
* There was no wheel handler at all: turning the wheel over a page scrolled the panel it sat in,
|
|
3265
|
+
* or nothing, and the only way down a page was the scroll buttons. Accumulated and sent as one
|
|
3266
|
+
* movement per burst, because a scroll gesture is fifty wheel events and fifty round trips is a
|
|
3267
|
+
* page that lurches instead of scrolling.
|
|
3268
|
+
*/
|
|
3269
|
+
img.onwheel = (ev) => {
|
|
3270
|
+
ev.preventDefault();
|
|
3271
|
+
scrolling.by += ev.deltaY;
|
|
3272
|
+
if (scrolling.timer) return;
|
|
3273
|
+
scrolling.timer = setTimeout(() => {
|
|
3274
|
+
const by = Math.round(scrolling.by);
|
|
3275
|
+
scrolling.by = 0;
|
|
3276
|
+
scrolling.timer = null;
|
|
3277
|
+
if (by !== 0) void browserDo({ action: 'scroll', by: by });
|
|
3278
|
+
}, SCROLL_BATCH_MS);
|
|
3279
|
+
};
|
|
3102
3280
|
|
|
3103
3281
|
// The picture is 1280 wide whatever it is displayed at, so a click has to be scaled back into
|
|
3104
3282
|
// page coordinates or it lands somewhere else entirely.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-client.js","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"ui-client.js","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+yIlB,CAAC;AACF,CAAC"}
|
package/dist/web/ui-css.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-css.d.ts","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AA8CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"ui-css.d.ts","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AA8CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAq9B3C"}
|
package/dist/web/ui-css.js
CHANGED
|
@@ -837,6 +837,8 @@ body[data-tint="soft"]{filter:contrast(.92) brightness(1.04)}
|
|
|
837
837
|
.termscroll{position:relative;flex:1;min-height:0;overflow:auto;padding:12px 14px 4px}
|
|
838
838
|
.termbody{margin:0;font-family:var(--mono);font-size:var(--term-font);line-height:1.55;
|
|
839
839
|
white-space:pre-wrap;word-break:break-word;color:var(--ink)}
|
|
840
|
+
/* A line is its own element so a new one can be added without rebuilding the rest. */
|
|
841
|
+
.termbody .tl{display:block}
|
|
840
842
|
.termrow{position:relative;display:flex;gap:8px;align-items:center;padding:2px 14px 12px}
|
|
841
843
|
.termps{font-family:var(--mono);font-size:var(--term-font);color:var(--cyan);flex:0 0 auto}
|
|
842
844
|
/*
|
package/dist/web/ui-css.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-css.js","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;;;;;;;;;;;;;;;;;gBAiBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI
|
|
1
|
+
{"version":3,"file":"ui-css.js","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;;;;;;;;;;;;;;;;;gBAiBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA67B9B,CAAC;AACF,CAAC"}
|
package/dist/web/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,wBAAgB,IAAI,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,wBAAgB,IAAI,IAAI,MAAM,CA2X7B"}
|
package/dist/web/ui.js
CHANGED
|
@@ -150,6 +150,16 @@ export function page() {
|
|
|
150
150
|
</label>
|
|
151
151
|
<input type="range" id="tbgop" min="4" max="40" value="14" title="How strongly it shows"
|
|
152
152
|
aria-label="Backdrop strength">
|
|
153
|
+
<!--
|
|
154
|
+
Your own picture, or the one KONECK ships with. Kept in this browser rather than on the
|
|
155
|
+
server: it is a preference about how your terminal looks, not something the machine needs
|
|
156
|
+
to know, and nothing about it should travel anywhere.
|
|
157
|
+
-->
|
|
158
|
+
<button type="button" class="termbtn" id="tbgpick"
|
|
159
|
+
title="Use a picture of your own">choose…</button>
|
|
160
|
+
<button type="button" class="termbtn" id="tbgreset" hidden
|
|
161
|
+
title="Back to the picture KONECK ships with">default</button>
|
|
162
|
+
<input type="file" id="tbgfile" accept="image/*" hidden>
|
|
153
163
|
<span class="termgap"></span>
|
|
154
164
|
<button type="button" class="termbtn" id="tfontdown" title="Smaller text">A−</button>
|
|
155
165
|
<button type="button" class="termbtn" id="tfontup" title="Larger text">A+</button>
|
package/dist/web/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,UAAU,IAAI;IAClB,OAAO;;;;;;;SAOA,GAAG,CAAC,SAAS,CAAC
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,UAAU,IAAI;IAClB,OAAO;;;;;;;SAOA,GAAG,CAAC,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA+WF,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;EAC7C,YAAY,EAAE;;eAED,CAAC;AAChB,CAAC"}
|