@bloopjs/web 0.0.101 → 0.0.103
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/debugui/components/BottomBar.d.ts.map +1 -1
- package/dist/debugui/components/LoadTapeDialog.d.ts.map +1 -1
- package/dist/debugui/components/TopBar.d.ts.map +1 -1
- package/dist/debugui/components/VerticalBar.d.ts +2 -1
- package/dist/debugui/components/VerticalBar.d.ts.map +1 -1
- package/dist/debugui/state.d.ts +4 -1
- package/dist/debugui/state.d.ts.map +1 -1
- package/dist/debugui/styles.d.ts +1 -1
- package/dist/debugui/styles.d.ts.map +1 -1
- package/dist/mod.js +189 -50
- package/dist/mod.js.map +11 -11
- package/package.json +3 -3
- package/src/debugui/components/BottomBar.tsx +28 -6
- package/src/debugui/components/LoadTapeDialog.tsx +55 -29
- package/src/debugui/components/Root.tsx +14 -4
- package/src/debugui/components/TopBar.tsx +11 -1
- package/src/debugui/components/VerticalBar.tsx +17 -1
- package/src/debugui/state.ts +52 -11
- package/src/debugui/styles.ts +53 -13
package/dist/mod.js
CHANGED
|
@@ -1450,7 +1450,7 @@ function readTapeHeader(tape) {
|
|
|
1450
1450
|
eventCount: view.getUint16(14, true)
|
|
1451
1451
|
};
|
|
1452
1452
|
}
|
|
1453
|
-
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
1453
|
+
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.103/wasm/bloop.wasm");
|
|
1454
1454
|
var MAX_ROLLBACK_FRAMES = 500;
|
|
1455
1455
|
var TIME_CTX_OFFSET = 0;
|
|
1456
1456
|
var INPUT_CTX_OFFSET = TIME_CTX_OFFSET + 4;
|
|
@@ -1556,6 +1556,9 @@ class Sim {
|
|
|
1556
1556
|
throw new Error(`failed to start recording, error code=${result}`);
|
|
1557
1557
|
}
|
|
1558
1558
|
}
|
|
1559
|
+
stopRecording() {
|
|
1560
|
+
this.wasm.stop_recording();
|
|
1561
|
+
}
|
|
1559
1562
|
saveTape() {
|
|
1560
1563
|
const tapeLen = this.wasm.get_tape_len();
|
|
1561
1564
|
const tapePtr = this.wasm.get_tape_ptr();
|
|
@@ -1621,21 +1624,33 @@ class Sim {
|
|
|
1621
1624
|
}
|
|
1622
1625
|
emit = {
|
|
1623
1626
|
keydown: (key, peerId = 0) => {
|
|
1627
|
+
if (this.#isPaused)
|
|
1628
|
+
return;
|
|
1624
1629
|
this.wasm.emit_keydown(keyToKeyCode(key), peerId);
|
|
1625
1630
|
},
|
|
1626
1631
|
keyup: (key, peerId = 0) => {
|
|
1632
|
+
if (this.#isPaused)
|
|
1633
|
+
return;
|
|
1627
1634
|
this.wasm.emit_keyup(keyToKeyCode(key), peerId);
|
|
1628
1635
|
},
|
|
1629
1636
|
mousemove: (x, y, peerId = 0) => {
|
|
1637
|
+
if (this.#isPaused)
|
|
1638
|
+
return;
|
|
1630
1639
|
this.wasm.emit_mousemove(x, y, peerId);
|
|
1631
1640
|
},
|
|
1632
1641
|
mousedown: (button, peerId = 0) => {
|
|
1642
|
+
if (this.#isPaused)
|
|
1643
|
+
return;
|
|
1633
1644
|
this.wasm.emit_mousedown(mouseButtonToMouseButtonCode(button), peerId);
|
|
1634
1645
|
},
|
|
1635
1646
|
mouseup: (button, peerId = 0) => {
|
|
1647
|
+
if (this.#isPaused)
|
|
1648
|
+
return;
|
|
1636
1649
|
this.wasm.emit_mouseup(mouseButtonToMouseButtonCode(button), peerId);
|
|
1637
1650
|
},
|
|
1638
1651
|
mousewheel: (x, y, peerId = 0) => {
|
|
1652
|
+
if (this.#isPaused)
|
|
1653
|
+
return;
|
|
1639
1654
|
this.wasm.emit_mousewheel(x, y, peerId);
|
|
1640
1655
|
},
|
|
1641
1656
|
resize: (width, height, physicalWidth, physicalHeight, pixelRatio) => {
|
|
@@ -3309,7 +3324,7 @@ function readTapeHeader2(tape) {
|
|
|
3309
3324
|
eventCount: view.getUint16(14, true)
|
|
3310
3325
|
};
|
|
3311
3326
|
}
|
|
3312
|
-
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
3327
|
+
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.103/wasm/bloop.wasm");
|
|
3313
3328
|
var TIME_CTX_OFFSET2 = 0;
|
|
3314
3329
|
var INPUT_CTX_OFFSET2 = TIME_CTX_OFFSET2 + 4;
|
|
3315
3330
|
var EVENTS_OFFSET2 = INPUT_CTX_OFFSET2 + 4;
|
|
@@ -4432,9 +4447,12 @@ var onJumpForward = d3(null);
|
|
|
4432
4447
|
var onSeek = d3(null);
|
|
4433
4448
|
var onLoadTape = d3(null);
|
|
4434
4449
|
var onReplayLastTape = d3(null);
|
|
4450
|
+
var onReplayLastSaved = d3(null);
|
|
4435
4451
|
var onSaveTape = d3(null);
|
|
4436
4452
|
var lastTapeName = d3(null);
|
|
4453
|
+
var lastSavedTapeName = d3(null);
|
|
4437
4454
|
var isLoadDialogOpen = d3(false);
|
|
4455
|
+
var onToggleRecording = d3(null);
|
|
4438
4456
|
var debugState = {
|
|
4439
4457
|
layoutMode,
|
|
4440
4458
|
isVisible: w3(() => layoutMode.value !== "off"),
|
|
@@ -4465,9 +4483,12 @@ var debugState = {
|
|
|
4465
4483
|
onSeek,
|
|
4466
4484
|
onLoadTape,
|
|
4467
4485
|
onReplayLastTape,
|
|
4486
|
+
onReplayLastSaved,
|
|
4468
4487
|
onSaveTape,
|
|
4469
4488
|
lastTapeName,
|
|
4470
|
-
|
|
4489
|
+
lastSavedTapeName,
|
|
4490
|
+
isLoadDialogOpen,
|
|
4491
|
+
onToggleRecording
|
|
4471
4492
|
};
|
|
4472
4493
|
function cycleLayout() {
|
|
4473
4494
|
const current = layoutMode.value;
|
|
@@ -4603,12 +4624,20 @@ function wirePlaybarHandlers(app) {
|
|
|
4603
4624
|
};
|
|
4604
4625
|
debugState.onSeek.value = (ratio) => {
|
|
4605
4626
|
if (app.sim.hasHistory) {
|
|
4627
|
+
app.sim.pause();
|
|
4606
4628
|
const startFrame = debugState.tapeStartFrame.value;
|
|
4607
4629
|
const frameCount = debugState.tapeFrameCount.value;
|
|
4608
4630
|
const targetFrame = startFrame + Math.floor(ratio * frameCount);
|
|
4609
4631
|
app.sim.seek(targetFrame);
|
|
4610
4632
|
}
|
|
4611
4633
|
};
|
|
4634
|
+
debugState.onToggleRecording.value = () => {
|
|
4635
|
+
if (app.sim.isRecording) {
|
|
4636
|
+
app.sim.stopRecording();
|
|
4637
|
+
} else {
|
|
4638
|
+
app.sim.record();
|
|
4639
|
+
}
|
|
4640
|
+
};
|
|
4612
4641
|
}
|
|
4613
4642
|
function wireTapeDragDrop(canvas, app) {
|
|
4614
4643
|
canvas.addEventListener("dragover", (e4) => {
|
|
@@ -4627,7 +4656,8 @@ function wireTapeDragDrop(canvas, app) {
|
|
|
4627
4656
|
}
|
|
4628
4657
|
var TAPE_DB_NAME = "bloop-debug";
|
|
4629
4658
|
var TAPE_STORE_NAME = "tapes";
|
|
4630
|
-
var
|
|
4659
|
+
var TAPE_KEY_LOADED = "last-loaded";
|
|
4660
|
+
var TAPE_KEY_SAVED = "last-saved";
|
|
4631
4661
|
function openTapeDB() {
|
|
4632
4662
|
return new Promise((resolve, reject) => {
|
|
4633
4663
|
const request = indexedDB.open(TAPE_DB_NAME, 1);
|
|
@@ -4638,21 +4668,21 @@ function openTapeDB() {
|
|
|
4638
4668
|
};
|
|
4639
4669
|
});
|
|
4640
4670
|
}
|
|
4641
|
-
async function saveTapeToStorage(bytes, fileName) {
|
|
4671
|
+
async function saveTapeToStorage(bytes, fileName, key = TAPE_KEY_LOADED) {
|
|
4642
4672
|
const db = await openTapeDB();
|
|
4643
4673
|
return new Promise((resolve, reject) => {
|
|
4644
4674
|
const tx = db.transaction(TAPE_STORE_NAME, "readwrite");
|
|
4645
|
-
tx.objectStore(TAPE_STORE_NAME).put({ bytes, fileName },
|
|
4675
|
+
tx.objectStore(TAPE_STORE_NAME).put({ bytes, fileName }, key);
|
|
4646
4676
|
tx.oncomplete = () => resolve();
|
|
4647
4677
|
tx.onerror = () => reject(tx.error);
|
|
4648
4678
|
});
|
|
4649
4679
|
}
|
|
4650
|
-
async function loadTapeFromStorage() {
|
|
4680
|
+
async function loadTapeFromStorage(key = TAPE_KEY_LOADED) {
|
|
4651
4681
|
try {
|
|
4652
4682
|
const db = await openTapeDB();
|
|
4653
4683
|
return new Promise((resolve, reject) => {
|
|
4654
4684
|
const tx = db.transaction(TAPE_STORE_NAME, "readonly");
|
|
4655
|
-
const request = tx.objectStore(TAPE_STORE_NAME).get(
|
|
4685
|
+
const request = tx.objectStore(TAPE_STORE_NAME).get(key);
|
|
4656
4686
|
request.onsuccess = () => resolve(request.result ?? null);
|
|
4657
4687
|
request.onerror = () => reject(request.error);
|
|
4658
4688
|
});
|
|
@@ -4661,32 +4691,46 @@ async function loadTapeFromStorage() {
|
|
|
4661
4691
|
}
|
|
4662
4692
|
}
|
|
4663
4693
|
async function checkForSavedTape() {
|
|
4664
|
-
const saved = await
|
|
4665
|
-
|
|
4694
|
+
const [loaded, saved] = await Promise.all([
|
|
4695
|
+
loadTapeFromStorage(TAPE_KEY_LOADED),
|
|
4696
|
+
loadTapeFromStorage(TAPE_KEY_SAVED)
|
|
4697
|
+
]);
|
|
4698
|
+
debugState.lastTapeName.value = loaded?.fileName ?? null;
|
|
4699
|
+
debugState.lastSavedTapeName.value = saved?.fileName ?? null;
|
|
4666
4700
|
}
|
|
4667
4701
|
function wireTapeLoadHandlers(app) {
|
|
4668
4702
|
debugState.onLoadTape.value = async (bytes, fileName) => {
|
|
4669
4703
|
app.loadTape(bytes);
|
|
4670
|
-
await saveTapeToStorage(bytes, fileName);
|
|
4704
|
+
await saveTapeToStorage(bytes, fileName, TAPE_KEY_LOADED);
|
|
4671
4705
|
debugState.lastTapeName.value = fileName;
|
|
4672
4706
|
debugState.isLoadDialogOpen.value = false;
|
|
4673
4707
|
};
|
|
4674
4708
|
debugState.onReplayLastTape.value = async () => {
|
|
4675
|
-
const saved = await loadTapeFromStorage();
|
|
4709
|
+
const saved = await loadTapeFromStorage(TAPE_KEY_LOADED);
|
|
4676
4710
|
if (saved) {
|
|
4677
4711
|
app.loadTape(saved.bytes);
|
|
4678
4712
|
debugState.isLoadDialogOpen.value = false;
|
|
4679
4713
|
}
|
|
4680
4714
|
};
|
|
4681
|
-
debugState.
|
|
4715
|
+
debugState.onReplayLastSaved.value = async () => {
|
|
4716
|
+
const saved = await loadTapeFromStorage(TAPE_KEY_SAVED);
|
|
4717
|
+
if (saved) {
|
|
4718
|
+
app.loadTape(saved.bytes);
|
|
4719
|
+
debugState.isLoadDialogOpen.value = false;
|
|
4720
|
+
}
|
|
4721
|
+
};
|
|
4722
|
+
debugState.onSaveTape.value = async () => {
|
|
4682
4723
|
if (!app.sim.hasHistory)
|
|
4683
4724
|
return;
|
|
4684
4725
|
const tape = app.sim.saveTape();
|
|
4726
|
+
const fileName = `tape-${Date.now()}.bloop`;
|
|
4727
|
+
await saveTapeToStorage(tape, fileName, TAPE_KEY_SAVED);
|
|
4728
|
+
debugState.lastSavedTapeName.value = fileName;
|
|
4685
4729
|
const blob = new Blob([tape], { type: "application/octet-stream" });
|
|
4686
4730
|
const url = URL.createObjectURL(blob);
|
|
4687
4731
|
const a4 = document.createElement("a");
|
|
4688
4732
|
a4.href = url;
|
|
4689
|
-
a4.download =
|
|
4733
|
+
a4.download = fileName;
|
|
4690
4734
|
a4.click();
|
|
4691
4735
|
URL.revokeObjectURL(url);
|
|
4692
4736
|
};
|
|
@@ -4970,8 +5014,14 @@ function TopBar({ leftLabel, rightLabel }) {
|
|
|
4970
5014
|
const frameNumber2 = debugState.frameNumber.value;
|
|
4971
5015
|
const rtt = debugState.netStatus.value.rtt;
|
|
4972
5016
|
const isOnline = debugState.netStatus.value.peers.length > 0;
|
|
5017
|
+
const stopPropagation = q2((e4) => {
|
|
5018
|
+
e4.stopPropagation();
|
|
5019
|
+
}, []);
|
|
4973
5020
|
return /* @__PURE__ */ u4("div", {
|
|
4974
5021
|
className: "top-bar",
|
|
5022
|
+
onMouseDown: stopPropagation,
|
|
5023
|
+
onMouseUp: stopPropagation,
|
|
5024
|
+
onClick: stopPropagation,
|
|
4975
5025
|
children: [
|
|
4976
5026
|
/* @__PURE__ */ u4("span", {
|
|
4977
5027
|
className: "top-bar-side-label",
|
|
@@ -5037,18 +5087,31 @@ function VerticalBar({
|
|
|
5037
5087
|
value,
|
|
5038
5088
|
max,
|
|
5039
5089
|
side,
|
|
5040
|
-
color = "#4a9eff"
|
|
5090
|
+
color = "#4a9eff",
|
|
5091
|
+
displayValue
|
|
5041
5092
|
}) {
|
|
5042
5093
|
const percentage = max > 0 ? Math.min(100, value / max * 100) : 0;
|
|
5094
|
+
const stopPropagation = q2((e4) => {
|
|
5095
|
+
e4.stopPropagation();
|
|
5096
|
+
}, []);
|
|
5043
5097
|
return /* @__PURE__ */ u4("div", {
|
|
5044
5098
|
className: `${side}-bar`,
|
|
5099
|
+
onMouseDown: stopPropagation,
|
|
5100
|
+
onMouseUp: stopPropagation,
|
|
5101
|
+
onClick: stopPropagation,
|
|
5045
5102
|
children: /* @__PURE__ */ u4("div", {
|
|
5046
5103
|
className: "vertical-bar",
|
|
5047
|
-
children:
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5104
|
+
children: [
|
|
5105
|
+
/* @__PURE__ */ u4("div", {
|
|
5106
|
+
className: "vertical-bar-fill",
|
|
5107
|
+
style: { height: `${percentage}%`, background: color }
|
|
5108
|
+
}, undefined, false, undefined, this),
|
|
5109
|
+
displayValue && /* @__PURE__ */ u4("span", {
|
|
5110
|
+
className: `vertical-bar-popover ${side}`,
|
|
5111
|
+
children: displayValue
|
|
5112
|
+
}, undefined, false, undefined, this)
|
|
5113
|
+
]
|
|
5114
|
+
}, undefined, true, undefined, this)
|
|
5052
5115
|
}, undefined, false, undefined, this);
|
|
5053
5116
|
}
|
|
5054
5117
|
|
|
@@ -5058,7 +5121,6 @@ function LoadTapeDialog() {
|
|
|
5058
5121
|
const fileInputRef = A2(null);
|
|
5059
5122
|
const [isDragOver, setIsDragOver] = d2(false);
|
|
5060
5123
|
const isOpen = debugState.isLoadDialogOpen.value;
|
|
5061
|
-
const lastTapeName2 = debugState.lastTapeName.value;
|
|
5062
5124
|
y2(() => {
|
|
5063
5125
|
const dialog = dialogRef.current;
|
|
5064
5126
|
if (!dialog)
|
|
@@ -5109,11 +5171,20 @@ function LoadTapeDialog() {
|
|
|
5109
5171
|
const handleReplayLast = q2(() => {
|
|
5110
5172
|
debugState.onReplayLastTape.value?.();
|
|
5111
5173
|
}, []);
|
|
5174
|
+
const handleReplayLastSaved = q2(() => {
|
|
5175
|
+
debugState.onReplayLastSaved.value?.();
|
|
5176
|
+
}, []);
|
|
5177
|
+
const handleDialogClick = q2((e4) => {
|
|
5178
|
+
if (e4.target === e4.currentTarget) {
|
|
5179
|
+
debugState.isLoadDialogOpen.value = false;
|
|
5180
|
+
}
|
|
5181
|
+
}, []);
|
|
5112
5182
|
return /* @__PURE__ */ u4("dialog", {
|
|
5113
5183
|
ref: dialogRef,
|
|
5114
5184
|
className: "load-tape-dialog",
|
|
5115
5185
|
onClose: handleClose,
|
|
5116
|
-
|
|
5186
|
+
onClick: handleDialogClick,
|
|
5187
|
+
children: isOpen && /* @__PURE__ */ u4("div", {
|
|
5117
5188
|
className: "load-tape-dialog-content",
|
|
5118
5189
|
children: [
|
|
5119
5190
|
/* @__PURE__ */ u4("h3", {
|
|
@@ -5141,12 +5212,17 @@ function LoadTapeDialog() {
|
|
|
5141
5212
|
className: "hidden-file-input",
|
|
5142
5213
|
onChange: handleFileInputChange
|
|
5143
5214
|
}, undefined, false, undefined, this),
|
|
5144
|
-
|
|
5215
|
+
debugState.lastSavedTapeName.value && /* @__PURE__ */ u4("button", {
|
|
5216
|
+
className: "replay-last-btn",
|
|
5217
|
+
onClick: handleReplayLastSaved,
|
|
5218
|
+
children: "Replay last saved tape"
|
|
5219
|
+
}, undefined, false, undefined, this),
|
|
5220
|
+
debugState.lastTapeName.value && /* @__PURE__ */ u4("button", {
|
|
5145
5221
|
className: "replay-last-btn",
|
|
5146
5222
|
onClick: handleReplayLast,
|
|
5147
5223
|
children: [
|
|
5148
|
-
"Replay last: ",
|
|
5149
|
-
|
|
5224
|
+
"Replay last loaded: ",
|
|
5225
|
+
debugState.lastTapeName.value
|
|
5150
5226
|
]
|
|
5151
5227
|
}, undefined, true, undefined, this)
|
|
5152
5228
|
]
|
|
@@ -5157,6 +5233,14 @@ function LoadTapeDialog() {
|
|
|
5157
5233
|
// src/debugui/components/BottomBar.tsx
|
|
5158
5234
|
var iconProps = { width: 14, height: 14, viewBox: "0 0 24 24", fill: "currentColor" };
|
|
5159
5235
|
var Icons = {
|
|
5236
|
+
record: /* @__PURE__ */ u4("svg", {
|
|
5237
|
+
...iconProps,
|
|
5238
|
+
children: /* @__PURE__ */ u4("circle", {
|
|
5239
|
+
cx: "12",
|
|
5240
|
+
cy: "12",
|
|
5241
|
+
r: "8"
|
|
5242
|
+
}, undefined, false, undefined, this)
|
|
5243
|
+
}, undefined, false, undefined, this),
|
|
5160
5244
|
jumpBack: /* @__PURE__ */ u4("svg", {
|
|
5161
5245
|
...iconProps,
|
|
5162
5246
|
children: /* @__PURE__ */ u4("path", {
|
|
@@ -5299,22 +5383,33 @@ function BottomBar() {
|
|
|
5299
5383
|
const handleSaveTapeClick = q2(() => {
|
|
5300
5384
|
debugState.onSaveTape.value?.();
|
|
5301
5385
|
}, []);
|
|
5386
|
+
const handleToggleRecording = q2(() => {
|
|
5387
|
+
debugState.onToggleRecording.value?.();
|
|
5388
|
+
}, []);
|
|
5389
|
+
const stopPropagation = q2((e4) => {
|
|
5390
|
+
e4.stopPropagation();
|
|
5391
|
+
}, []);
|
|
5302
5392
|
return /* @__PURE__ */ u4("div", {
|
|
5303
5393
|
className: "bottom-bar",
|
|
5394
|
+
onMouseDown: stopPropagation,
|
|
5395
|
+
onMouseUp: stopPropagation,
|
|
5396
|
+
onClick: stopPropagation,
|
|
5304
5397
|
children: [
|
|
5305
5398
|
/* @__PURE__ */ u4("div", {
|
|
5306
5399
|
className: "playbar-controls",
|
|
5307
5400
|
children: [
|
|
5308
|
-
|
|
5309
|
-
className: "recording
|
|
5310
|
-
|
|
5401
|
+
/* @__PURE__ */ u4("button", {
|
|
5402
|
+
className: `playbar-btn record-btn ${isRecording2 ? "recording" : ""}`,
|
|
5403
|
+
onClick: handleToggleRecording,
|
|
5311
5404
|
children: [
|
|
5312
|
-
|
|
5313
|
-
|
|
5405
|
+
Icons.record,
|
|
5406
|
+
isRecording2 && /* @__PURE__ */ u4("span", {
|
|
5407
|
+
className: "btn-label",
|
|
5408
|
+
children: "REC"
|
|
5314
5409
|
}, undefined, false, undefined, this),
|
|
5315
5410
|
/* @__PURE__ */ u4("span", {
|
|
5316
|
-
className: "
|
|
5317
|
-
children: "
|
|
5411
|
+
className: "tooltip tooltip-left",
|
|
5412
|
+
children: isRecording2 ? "Stop recording" : "Start recording"
|
|
5318
5413
|
}, undefined, false, undefined, this)
|
|
5319
5414
|
]
|
|
5320
5415
|
}, undefined, true, undefined, this),
|
|
@@ -5525,11 +5620,13 @@ function LetterboxedLayout({ canvas }) {
|
|
|
5525
5620
|
const hmrFlash2 = debugState.hmrFlash.value;
|
|
5526
5621
|
const leftValue = isOnline ? Math.abs(advantage) : frameTime2;
|
|
5527
5622
|
const leftMax = isOnline ? 10 : 16.67;
|
|
5528
|
-
const leftLabel = isOnline ? "
|
|
5623
|
+
const leftLabel = isOnline ? "adv" : "time";
|
|
5529
5624
|
const leftColor = isOnline ? advantage >= 0 ? "#4a9eff" : "#ff4a4a" : frameTime2 > 16.67 ? "#ff4a4a" : "#4aff4a";
|
|
5625
|
+
const leftDisplayValue = isOnline ? `${advantage >= 0 ? "+" : ""}${advantage} frames` : `${frameTime2.toFixed(1)}ms`;
|
|
5530
5626
|
const rightValue = isOnline ? 0 : snapshotSize2;
|
|
5531
5627
|
const rightMax = isOnline ? 10 : 1e4;
|
|
5532
|
-
const rightLabel = isOnline ? "
|
|
5628
|
+
const rightLabel = isOnline ? "rb" : "size";
|
|
5629
|
+
const rightDisplayValue = isOnline ? "0 frames" : snapshotSize2 >= 1000 ? `${(snapshotSize2 / 1000).toFixed(1)}kb` : `${snapshotSize2}b`;
|
|
5533
5630
|
const gameClassName = hmrFlash2 ? "letterboxed-game hmr-flash" : "letterboxed-game";
|
|
5534
5631
|
return /* @__PURE__ */ u4("main", {
|
|
5535
5632
|
className: "layout-letterboxed",
|
|
@@ -5542,7 +5639,8 @@ function LetterboxedLayout({ canvas }) {
|
|
|
5542
5639
|
value: leftValue,
|
|
5543
5640
|
max: leftMax,
|
|
5544
5641
|
side: "left",
|
|
5545
|
-
color: leftColor
|
|
5642
|
+
color: leftColor,
|
|
5643
|
+
displayValue: leftDisplayValue
|
|
5546
5644
|
}, undefined, false, undefined, this),
|
|
5547
5645
|
/* @__PURE__ */ u4("div", {
|
|
5548
5646
|
className: gameClassName,
|
|
@@ -5553,7 +5651,8 @@ function LetterboxedLayout({ canvas }) {
|
|
|
5553
5651
|
/* @__PURE__ */ u4(VerticalBar, {
|
|
5554
5652
|
value: rightValue,
|
|
5555
5653
|
max: rightMax,
|
|
5556
|
-
side: "right"
|
|
5654
|
+
side: "right",
|
|
5655
|
+
displayValue: rightDisplayValue
|
|
5557
5656
|
}, undefined, false, undefined, this),
|
|
5558
5657
|
/* @__PURE__ */ u4(BottomBar, {}, undefined, false, undefined, this)
|
|
5559
5658
|
]
|
|
@@ -5737,6 +5836,7 @@ var styles = `
|
|
|
5737
5836
|
font-family: monospace;
|
|
5738
5837
|
font-size: 12px;
|
|
5739
5838
|
padding: 0;
|
|
5839
|
+
user-select: none;
|
|
5740
5840
|
}
|
|
5741
5841
|
|
|
5742
5842
|
.top-bar-side-label {
|
|
@@ -5790,6 +5890,7 @@ var styles = `
|
|
|
5790
5890
|
justify-content: flex-end;
|
|
5791
5891
|
background: #111;
|
|
5792
5892
|
padding: 4px 0;
|
|
5893
|
+
user-select: none;
|
|
5793
5894
|
}
|
|
5794
5895
|
|
|
5795
5896
|
.right-bar {
|
|
@@ -5800,6 +5901,7 @@ var styles = `
|
|
|
5800
5901
|
justify-content: flex-end;
|
|
5801
5902
|
background: #111;
|
|
5802
5903
|
padding: 4px 0;
|
|
5904
|
+
user-select: none;
|
|
5803
5905
|
}
|
|
5804
5906
|
|
|
5805
5907
|
.vertical-bar {
|
|
@@ -5808,7 +5910,6 @@ var styles = `
|
|
|
5808
5910
|
background: #333;
|
|
5809
5911
|
border-radius: 2px;
|
|
5810
5912
|
position: relative;
|
|
5811
|
-
overflow: hidden;
|
|
5812
5913
|
}
|
|
5813
5914
|
|
|
5814
5915
|
.vertical-bar-fill {
|
|
@@ -5821,6 +5922,37 @@ var styles = `
|
|
|
5821
5922
|
transition: height 0.1s ease-out;
|
|
5822
5923
|
}
|
|
5823
5924
|
|
|
5925
|
+
.vertical-bar-popover {
|
|
5926
|
+
position: absolute;
|
|
5927
|
+
top: 50%;
|
|
5928
|
+
transform: translateY(-50%);
|
|
5929
|
+
background: #222;
|
|
5930
|
+
color: #ccc;
|
|
5931
|
+
padding: 4px 8px;
|
|
5932
|
+
border-radius: 4px;
|
|
5933
|
+
font-size: 10px;
|
|
5934
|
+
font-family: monospace;
|
|
5935
|
+
white-space: nowrap;
|
|
5936
|
+
opacity: 0;
|
|
5937
|
+
visibility: hidden;
|
|
5938
|
+
transition: opacity 0.15s;
|
|
5939
|
+
pointer-events: none;
|
|
5940
|
+
z-index: 10;
|
|
5941
|
+
}
|
|
5942
|
+
|
|
5943
|
+
.vertical-bar-popover.left {
|
|
5944
|
+
left: calc(100% + 8px);
|
|
5945
|
+
}
|
|
5946
|
+
|
|
5947
|
+
.vertical-bar-popover.right {
|
|
5948
|
+
right: calc(100% + 8px);
|
|
5949
|
+
}
|
|
5950
|
+
|
|
5951
|
+
.vertical-bar:hover .vertical-bar-popover {
|
|
5952
|
+
opacity: 1;
|
|
5953
|
+
visibility: visible;
|
|
5954
|
+
}
|
|
5955
|
+
|
|
5824
5956
|
|
|
5825
5957
|
.bottom-bar {
|
|
5826
5958
|
grid-area: bottom-bar;
|
|
@@ -5830,6 +5962,7 @@ var styles = `
|
|
|
5830
5962
|
/* Mobile-first: more padding */
|
|
5831
5963
|
padding: 0 16px;
|
|
5832
5964
|
gap: 12px;
|
|
5965
|
+
user-select: none;
|
|
5833
5966
|
}
|
|
5834
5967
|
|
|
5835
5968
|
/* Desktop: tighter padding */
|
|
@@ -5847,22 +5980,16 @@ var styles = `
|
|
|
5847
5980
|
flex-shrink: 0;
|
|
5848
5981
|
}
|
|
5849
5982
|
|
|
5850
|
-
/*
|
|
5851
|
-
.
|
|
5852
|
-
|
|
5853
|
-
align-items: center;
|
|
5854
|
-
margin-right: 4px;
|
|
5983
|
+
/* Record button */
|
|
5984
|
+
.record-btn {
|
|
5985
|
+
color: #666;
|
|
5855
5986
|
}
|
|
5856
5987
|
|
|
5857
|
-
.
|
|
5858
|
-
|
|
5988
|
+
.record-btn.recording {
|
|
5989
|
+
color: #ff4444;
|
|
5859
5990
|
}
|
|
5860
5991
|
|
|
5861
|
-
.recording
|
|
5862
|
-
width: 10px;
|
|
5863
|
-
height: 10px;
|
|
5864
|
-
background: #ff4444;
|
|
5865
|
-
border-radius: 50%;
|
|
5992
|
+
.record-btn.recording svg {
|
|
5866
5993
|
animation: recording-pulse 1s ease-in-out infinite;
|
|
5867
5994
|
}
|
|
5868
5995
|
|
|
@@ -5871,6 +5998,17 @@ var styles = `
|
|
|
5871
5998
|
50% { opacity: 0.4; }
|
|
5872
5999
|
}
|
|
5873
6000
|
|
|
6001
|
+
/* Desktop: show REC label when recording */
|
|
6002
|
+
@media (min-width: 769px) {
|
|
6003
|
+
.record-btn.recording {
|
|
6004
|
+
width: auto;
|
|
6005
|
+
padding: 0 6px;
|
|
6006
|
+
gap: 4px;
|
|
6007
|
+
background: rgba(255, 68, 68, 0.15);
|
|
6008
|
+
border-radius: 3px;
|
|
6009
|
+
}
|
|
6010
|
+
}
|
|
6011
|
+
|
|
5874
6012
|
/* Replay indicator - mobile: hidden */
|
|
5875
6013
|
.replay-indicator {
|
|
5876
6014
|
display: none;
|
|
@@ -6032,6 +6170,7 @@ var styles = `
|
|
|
6032
6170
|
position: relative;
|
|
6033
6171
|
cursor: pointer;
|
|
6034
6172
|
overflow: hidden;
|
|
6173
|
+
user-select: none;
|
|
6035
6174
|
}
|
|
6036
6175
|
|
|
6037
6176
|
/* Desktop: smaller seek bar */
|
|
@@ -7686,5 +7825,5 @@ export {
|
|
|
7686
7825
|
App
|
|
7687
7826
|
};
|
|
7688
7827
|
|
|
7689
|
-
//# debugId=
|
|
7828
|
+
//# debugId=A1466E71356AC5F764756E2164756E21
|
|
7690
7829
|
//# sourceMappingURL=mod.js.map
|