@bloopjs/web 0.0.90 → 0.0.92
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/App.d.ts.map +1 -1
- package/dist/debugui/components/BottomBar.d.ts.map +1 -1
- package/dist/debugui/components/LoadTapeDialog.d.ts +2 -0
- package/dist/debugui/components/LoadTapeDialog.d.ts.map +1 -0
- package/dist/debugui/state.d.ts +9 -0
- 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 +560 -64
- package/dist/mod.js.map +10 -9
- package/package.json +3 -3
- package/src/App.ts +3 -1
- package/src/debugui/components/BottomBar.tsx +25 -5
- package/src/debugui/components/LoadTapeDialog.tsx +112 -0
- package/src/debugui/state.ts +105 -0
- package/src/debugui/styles.ts +256 -18
package/dist/mod.js
CHANGED
|
@@ -1432,7 +1432,7 @@ function readTapeHeader(tape) {
|
|
|
1432
1432
|
eventCount: view.getUint16(14, true)
|
|
1433
1433
|
};
|
|
1434
1434
|
}
|
|
1435
|
-
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
1435
|
+
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.92/wasm/bloop.wasm");
|
|
1436
1436
|
var MAX_ROLLBACK_FRAMES = 500;
|
|
1437
1437
|
var TIME_CTX_OFFSET = 0;
|
|
1438
1438
|
var INPUT_CTX_OFFSET = TIME_CTX_OFFSET + 4;
|
|
@@ -3273,7 +3273,7 @@ function readTapeHeader2(tape) {
|
|
|
3273
3273
|
eventCount: view.getUint16(14, true)
|
|
3274
3274
|
};
|
|
3275
3275
|
}
|
|
3276
|
-
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
3276
|
+
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.92/wasm/bloop.wasm");
|
|
3277
3277
|
var TIME_CTX_OFFSET2 = 0;
|
|
3278
3278
|
var INPUT_CTX_OFFSET2 = TIME_CTX_OFFSET2 + 4;
|
|
3279
3279
|
var EVENTS_OFFSET2 = INPUT_CTX_OFFSET2 + 4;
|
|
@@ -3283,6 +3283,7 @@ var SCREEN_CTX_OFFSET2 = NET_CTX_OFFSET2 + 4;
|
|
|
3283
3283
|
// src/debugui/mod.ts
|
|
3284
3284
|
var exports_mod = {};
|
|
3285
3285
|
__export(exports_mod, {
|
|
3286
|
+
wireTapeLoadHandlers: () => wireTapeLoadHandlers,
|
|
3286
3287
|
wireTapeDragDrop: () => wireTapeDragDrop,
|
|
3287
3288
|
wirePlaybarHandlers: () => wirePlaybarHandlers,
|
|
3288
3289
|
updatePeer: () => updatePeer,
|
|
@@ -3294,6 +3295,7 @@ __export(exports_mod, {
|
|
|
3294
3295
|
debugState: () => debugState,
|
|
3295
3296
|
cycleLayout: () => cycleLayout,
|
|
3296
3297
|
clearLogs: () => clearLogs,
|
|
3298
|
+
checkForSavedTape: () => checkForSavedTape,
|
|
3297
3299
|
addPeer: () => addPeer,
|
|
3298
3300
|
addLog: () => addLog,
|
|
3299
3301
|
DebugUi: () => DebugUi
|
|
@@ -3637,6 +3639,45 @@ function p2(n2, t3) {
|
|
|
3637
3639
|
var u3 = r2.__H || (r2.__H = { __: [], __h: [] });
|
|
3638
3640
|
return n2 >= u3.__.length && u3.__.push({}), u3.__[n2];
|
|
3639
3641
|
}
|
|
3642
|
+
function d2(n2) {
|
|
3643
|
+
return o2 = 1, h2(D2, n2);
|
|
3644
|
+
}
|
|
3645
|
+
function h2(n2, u3, i3) {
|
|
3646
|
+
var o3 = p2(t2++, 2);
|
|
3647
|
+
if (o3.t = n2, !o3.__c && (o3.__ = [i3 ? i3(u3) : D2(undefined, u3), function(n3) {
|
|
3648
|
+
var t3 = o3.__N ? o3.__N[0] : o3.__[0], r3 = o3.t(t3, n3);
|
|
3649
|
+
t3 !== r3 && (o3.__N = [r3, o3.__[1]], o3.__c.setState({}));
|
|
3650
|
+
}], o3.__c = r2, !r2.__f)) {
|
|
3651
|
+
var f3 = function(n3, t3, r3) {
|
|
3652
|
+
if (!o3.__c.__H)
|
|
3653
|
+
return true;
|
|
3654
|
+
var u4 = o3.__c.__H.__.filter(function(n4) {
|
|
3655
|
+
return !!n4.__c;
|
|
3656
|
+
});
|
|
3657
|
+
if (u4.every(function(n4) {
|
|
3658
|
+
return !n4.__N;
|
|
3659
|
+
}))
|
|
3660
|
+
return !c3 || c3.call(this, n3, t3, r3);
|
|
3661
|
+
var i4 = o3.__c.props !== n3;
|
|
3662
|
+
return u4.forEach(function(n4) {
|
|
3663
|
+
if (n4.__N) {
|
|
3664
|
+
var t4 = n4.__[0];
|
|
3665
|
+
n4.__ = n4.__N, n4.__N = undefined, t4 !== n4.__[0] && (i4 = true);
|
|
3666
|
+
}
|
|
3667
|
+
}), c3 && c3.call(this, n3, t3, r3) || i4;
|
|
3668
|
+
};
|
|
3669
|
+
r2.__f = true;
|
|
3670
|
+
var { shouldComponentUpdate: c3, componentWillUpdate: e3 } = r2;
|
|
3671
|
+
r2.componentWillUpdate = function(n3, t3, r3) {
|
|
3672
|
+
if (this.__e) {
|
|
3673
|
+
var u4 = c3;
|
|
3674
|
+
c3 = undefined, f3(n3, t3, r3), c3 = u4;
|
|
3675
|
+
}
|
|
3676
|
+
e3 && e3.call(this, n3, t3, r3);
|
|
3677
|
+
}, r2.shouldComponentUpdate = f3;
|
|
3678
|
+
}
|
|
3679
|
+
return o3.__N || o3.__;
|
|
3680
|
+
}
|
|
3640
3681
|
function y2(n2, u3) {
|
|
3641
3682
|
var i3 = p2(t2++, 3);
|
|
3642
3683
|
!c2.__s && C2(i3.__H, u3) && (i3.__ = n2, i3.u = u3, r2.__H.__h.push(i3));
|
|
@@ -3723,15 +3764,18 @@ function C2(n2, t3) {
|
|
|
3723
3764
|
return t4 !== n2[r3];
|
|
3724
3765
|
});
|
|
3725
3766
|
}
|
|
3767
|
+
function D2(n2, t3) {
|
|
3768
|
+
return typeof t3 == "function" ? t3(n2) : t3;
|
|
3769
|
+
}
|
|
3726
3770
|
|
|
3727
3771
|
// ../../node_modules/@preact/signals-core/dist/signals-core.module.js
|
|
3728
3772
|
var i3 = Symbol.for("preact-signals");
|
|
3729
3773
|
function t3() {
|
|
3730
3774
|
if (!(s3 > 1)) {
|
|
3731
3775
|
var i4, t4 = false;
|
|
3732
|
-
while (
|
|
3733
|
-
var r3 =
|
|
3734
|
-
|
|
3776
|
+
while (h3 !== undefined) {
|
|
3777
|
+
var r3 = h3;
|
|
3778
|
+
h3 = undefined;
|
|
3735
3779
|
f3++;
|
|
3736
3780
|
while (r3 !== undefined) {
|
|
3737
3781
|
var o3 = r3.o;
|
|
@@ -3766,7 +3810,7 @@ function n2(i4) {
|
|
|
3766
3810
|
o3 = t4;
|
|
3767
3811
|
}
|
|
3768
3812
|
}
|
|
3769
|
-
var
|
|
3813
|
+
var h3 = undefined;
|
|
3770
3814
|
var s3 = 0;
|
|
3771
3815
|
var f3 = 0;
|
|
3772
3816
|
var v3 = 0;
|
|
@@ -3897,7 +3941,7 @@ Object.defineProperty(u3.prototype, "value", { get: function() {
|
|
|
3897
3941
|
}
|
|
3898
3942
|
}
|
|
3899
3943
|
} });
|
|
3900
|
-
function
|
|
3944
|
+
function d3(i4, t4) {
|
|
3901
3945
|
return new u3(i4, t4);
|
|
3902
3946
|
}
|
|
3903
3947
|
function c3(i4) {
|
|
@@ -4097,8 +4141,8 @@ p3.prototype.S = function() {
|
|
|
4097
4141
|
p3.prototype.N = function() {
|
|
4098
4142
|
if (!(2 & this.f)) {
|
|
4099
4143
|
this.f |= 2;
|
|
4100
|
-
this.o =
|
|
4101
|
-
|
|
4144
|
+
this.o = h3;
|
|
4145
|
+
h3 = this;
|
|
4102
4146
|
}
|
|
4103
4147
|
};
|
|
4104
4148
|
p3.prototype.d = function() {
|
|
@@ -4128,12 +4172,12 @@ var s4;
|
|
|
4128
4172
|
function l4(i4, n3) {
|
|
4129
4173
|
l[i4] = n3.bind(null, l[i4] || function() {});
|
|
4130
4174
|
}
|
|
4131
|
-
function
|
|
4175
|
+
function d4(i4) {
|
|
4132
4176
|
if (s4)
|
|
4133
4177
|
s4();
|
|
4134
4178
|
s4 = i4 && i4.S();
|
|
4135
4179
|
}
|
|
4136
|
-
function
|
|
4180
|
+
function h4(i4) {
|
|
4137
4181
|
var r4 = this, f4 = i4.data, o4 = useSignal(f4);
|
|
4138
4182
|
o4.value = f4;
|
|
4139
4183
|
var e4 = T2(function() {
|
|
@@ -4159,8 +4203,8 @@ function h3(i4) {
|
|
|
4159
4203
|
}, []);
|
|
4160
4204
|
return e4.value;
|
|
4161
4205
|
}
|
|
4162
|
-
|
|
4163
|
-
Object.defineProperties(u3.prototype, { constructor: { configurable: true, value: undefined }, type: { configurable: true, value:
|
|
4206
|
+
h4.displayName = "_st";
|
|
4207
|
+
Object.defineProperties(u3.prototype, { constructor: { configurable: true, value: undefined }, type: { configurable: true, value: h4 }, props: { configurable: true, get: function() {
|
|
4164
4208
|
return { data: this };
|
|
4165
4209
|
} }, __b: { configurable: true, value: 1 } });
|
|
4166
4210
|
l4("__b", function(i4, r4) {
|
|
@@ -4180,7 +4224,7 @@ l4("__b", function(i4, r4) {
|
|
|
4180
4224
|
i4(r4);
|
|
4181
4225
|
});
|
|
4182
4226
|
l4("__r", function(i4, r4) {
|
|
4183
|
-
|
|
4227
|
+
d4();
|
|
4184
4228
|
var n3, t4 = r4.__c;
|
|
4185
4229
|
if (t4) {
|
|
4186
4230
|
t4.__$f &= -2;
|
|
@@ -4198,16 +4242,16 @@ l4("__r", function(i4, r4) {
|
|
|
4198
4242
|
}();
|
|
4199
4243
|
}
|
|
4200
4244
|
v4 = t4;
|
|
4201
|
-
|
|
4245
|
+
d4(n3);
|
|
4202
4246
|
i4(r4);
|
|
4203
4247
|
});
|
|
4204
4248
|
l4("__e", function(i4, r4, n3, t4) {
|
|
4205
|
-
|
|
4249
|
+
d4();
|
|
4206
4250
|
v4 = undefined;
|
|
4207
4251
|
i4(r4, n3, t4);
|
|
4208
4252
|
});
|
|
4209
4253
|
l4("diffed", function(i4, r4) {
|
|
4210
|
-
|
|
4254
|
+
d4();
|
|
4211
4255
|
v4 = undefined;
|
|
4212
4256
|
var n3;
|
|
4213
4257
|
if (typeof r4.type == "string" && (n3 = r4.__e)) {
|
|
@@ -4237,7 +4281,7 @@ l4("diffed", function(i4, r4) {
|
|
|
4237
4281
|
i4(r4);
|
|
4238
4282
|
});
|
|
4239
4283
|
function p4(i4, r4, n3, t4) {
|
|
4240
|
-
var f4 = r4 in i4 && i4.ownerSVGElement === undefined, o4 =
|
|
4284
|
+
var f4 = r4 in i4 && i4.ownerSVGElement === undefined, o4 = d3(n3);
|
|
4241
4285
|
return { o: function(i5, r5) {
|
|
4242
4286
|
o4.value = i5;
|
|
4243
4287
|
t4 = r5;
|
|
@@ -4310,7 +4354,7 @@ x.prototype.shouldComponentUpdate = function(i4, r4) {
|
|
|
4310
4354
|
};
|
|
4311
4355
|
function useSignal(i4) {
|
|
4312
4356
|
return T2(function() {
|
|
4313
|
-
return
|
|
4357
|
+
return d3(i4);
|
|
4314
4358
|
}, []);
|
|
4315
4359
|
}
|
|
4316
4360
|
function useSignalEffect(i4) {
|
|
@@ -4324,30 +4368,35 @@ function useSignalEffect(i4) {
|
|
|
4324
4368
|
}
|
|
4325
4369
|
|
|
4326
4370
|
// src/debugui/state.ts
|
|
4327
|
-
var layoutMode =
|
|
4328
|
-
var netStatus =
|
|
4371
|
+
var layoutMode = d3("off");
|
|
4372
|
+
var netStatus = d3({
|
|
4329
4373
|
ourId: null,
|
|
4330
4374
|
remoteId: null,
|
|
4331
4375
|
rtt: null,
|
|
4332
4376
|
peers: []
|
|
4333
4377
|
});
|
|
4334
|
-
var logs =
|
|
4335
|
-
var fps =
|
|
4336
|
-
var frameTime =
|
|
4337
|
-
var snapshotSize =
|
|
4338
|
-
var frameNumber =
|
|
4339
|
-
var hmrFlash =
|
|
4340
|
-
var isPlaying =
|
|
4341
|
-
var tapeUtilization =
|
|
4342
|
-
var playheadPosition =
|
|
4343
|
-
var tapeStartFrame =
|
|
4344
|
-
var tapeFrameCount =
|
|
4345
|
-
var onJumpBack =
|
|
4346
|
-
var onStepBack =
|
|
4347
|
-
var onPlayPause =
|
|
4348
|
-
var onStepForward =
|
|
4349
|
-
var onJumpForward =
|
|
4350
|
-
var onSeek =
|
|
4378
|
+
var logs = d3([]);
|
|
4379
|
+
var fps = d3(0);
|
|
4380
|
+
var frameTime = d3(0);
|
|
4381
|
+
var snapshotSize = d3(0);
|
|
4382
|
+
var frameNumber = d3(0);
|
|
4383
|
+
var hmrFlash = d3(false);
|
|
4384
|
+
var isPlaying = d3(true);
|
|
4385
|
+
var tapeUtilization = d3(0);
|
|
4386
|
+
var playheadPosition = d3(0);
|
|
4387
|
+
var tapeStartFrame = d3(0);
|
|
4388
|
+
var tapeFrameCount = d3(0);
|
|
4389
|
+
var onJumpBack = d3(null);
|
|
4390
|
+
var onStepBack = d3(null);
|
|
4391
|
+
var onPlayPause = d3(null);
|
|
4392
|
+
var onStepForward = d3(null);
|
|
4393
|
+
var onJumpForward = d3(null);
|
|
4394
|
+
var onSeek = d3(null);
|
|
4395
|
+
var onLoadTape = d3(null);
|
|
4396
|
+
var onReplayLastTape = d3(null);
|
|
4397
|
+
var onSaveTape = d3(null);
|
|
4398
|
+
var lastTapeName = d3(null);
|
|
4399
|
+
var isLoadDialogOpen = d3(false);
|
|
4351
4400
|
var debugState = {
|
|
4352
4401
|
layoutMode,
|
|
4353
4402
|
isVisible: w3(() => layoutMode.value !== "off"),
|
|
@@ -4373,7 +4422,12 @@ var debugState = {
|
|
|
4373
4422
|
onPlayPause,
|
|
4374
4423
|
onStepForward,
|
|
4375
4424
|
onJumpForward,
|
|
4376
|
-
onSeek
|
|
4425
|
+
onSeek,
|
|
4426
|
+
onLoadTape,
|
|
4427
|
+
onReplayLastTape,
|
|
4428
|
+
onSaveTape,
|
|
4429
|
+
lastTapeName,
|
|
4430
|
+
isLoadDialogOpen
|
|
4377
4431
|
};
|
|
4378
4432
|
function cycleLayout() {
|
|
4379
4433
|
const current = layoutMode.value;
|
|
@@ -4529,6 +4583,73 @@ function wireTapeDragDrop(canvas, app) {
|
|
|
4529
4583
|
app.loadTape(bytes);
|
|
4530
4584
|
});
|
|
4531
4585
|
}
|
|
4586
|
+
var TAPE_DB_NAME = "bloop-debug";
|
|
4587
|
+
var TAPE_STORE_NAME = "tapes";
|
|
4588
|
+
var TAPE_KEY = "last";
|
|
4589
|
+
function openTapeDB() {
|
|
4590
|
+
return new Promise((resolve, reject) => {
|
|
4591
|
+
const request = indexedDB.open(TAPE_DB_NAME, 1);
|
|
4592
|
+
request.onerror = () => reject(request.error);
|
|
4593
|
+
request.onsuccess = () => resolve(request.result);
|
|
4594
|
+
request.onupgradeneeded = () => {
|
|
4595
|
+
request.result.createObjectStore(TAPE_STORE_NAME);
|
|
4596
|
+
};
|
|
4597
|
+
});
|
|
4598
|
+
}
|
|
4599
|
+
async function saveTapeToStorage(bytes, fileName) {
|
|
4600
|
+
const db = await openTapeDB();
|
|
4601
|
+
return new Promise((resolve, reject) => {
|
|
4602
|
+
const tx = db.transaction(TAPE_STORE_NAME, "readwrite");
|
|
4603
|
+
tx.objectStore(TAPE_STORE_NAME).put({ bytes, fileName }, TAPE_KEY);
|
|
4604
|
+
tx.oncomplete = () => resolve();
|
|
4605
|
+
tx.onerror = () => reject(tx.error);
|
|
4606
|
+
});
|
|
4607
|
+
}
|
|
4608
|
+
async function loadTapeFromStorage() {
|
|
4609
|
+
try {
|
|
4610
|
+
const db = await openTapeDB();
|
|
4611
|
+
return new Promise((resolve, reject) => {
|
|
4612
|
+
const tx = db.transaction(TAPE_STORE_NAME, "readonly");
|
|
4613
|
+
const request = tx.objectStore(TAPE_STORE_NAME).get(TAPE_KEY);
|
|
4614
|
+
request.onsuccess = () => resolve(request.result ?? null);
|
|
4615
|
+
request.onerror = () => reject(request.error);
|
|
4616
|
+
});
|
|
4617
|
+
} catch {
|
|
4618
|
+
return null;
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
async function checkForSavedTape() {
|
|
4622
|
+
const saved = await loadTapeFromStorage();
|
|
4623
|
+
debugState.lastTapeName.value = saved?.fileName ?? null;
|
|
4624
|
+
}
|
|
4625
|
+
function wireTapeLoadHandlers(app) {
|
|
4626
|
+
debugState.onLoadTape.value = async (bytes, fileName) => {
|
|
4627
|
+
app.loadTape(bytes);
|
|
4628
|
+
await saveTapeToStorage(bytes, fileName);
|
|
4629
|
+
debugState.lastTapeName.value = fileName;
|
|
4630
|
+
debugState.isLoadDialogOpen.value = false;
|
|
4631
|
+
};
|
|
4632
|
+
debugState.onReplayLastTape.value = async () => {
|
|
4633
|
+
const saved = await loadTapeFromStorage();
|
|
4634
|
+
if (saved) {
|
|
4635
|
+
app.loadTape(saved.bytes);
|
|
4636
|
+
debugState.isLoadDialogOpen.value = false;
|
|
4637
|
+
}
|
|
4638
|
+
};
|
|
4639
|
+
debugState.onSaveTape.value = () => {
|
|
4640
|
+
if (!app.sim.hasHistory)
|
|
4641
|
+
return;
|
|
4642
|
+
const tape = app.sim.saveTape();
|
|
4643
|
+
const blob = new Blob([tape], { type: "application/octet-stream" });
|
|
4644
|
+
const url = URL.createObjectURL(blob);
|
|
4645
|
+
const a4 = document.createElement("a");
|
|
4646
|
+
a4.href = url;
|
|
4647
|
+
a4.download = `tape-${Date.now()}.bloop`;
|
|
4648
|
+
a4.click();
|
|
4649
|
+
URL.revokeObjectURL(url);
|
|
4650
|
+
};
|
|
4651
|
+
checkForSavedTape();
|
|
4652
|
+
}
|
|
4532
4653
|
// ../../node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js
|
|
4533
4654
|
var f4 = 0;
|
|
4534
4655
|
function u4(e4, t4, n3, o4, i4, u5) {
|
|
@@ -4889,6 +5010,108 @@ function VerticalBar({
|
|
|
4889
5010
|
}, undefined, false, undefined, this);
|
|
4890
5011
|
}
|
|
4891
5012
|
|
|
5013
|
+
// src/debugui/components/LoadTapeDialog.tsx
|
|
5014
|
+
function LoadTapeDialog() {
|
|
5015
|
+
const dialogRef = A2(null);
|
|
5016
|
+
const fileInputRef = A2(null);
|
|
5017
|
+
const [isDragOver, setIsDragOver] = d2(false);
|
|
5018
|
+
const isOpen = debugState.isLoadDialogOpen.value;
|
|
5019
|
+
const lastTapeName2 = debugState.lastTapeName.value;
|
|
5020
|
+
y2(() => {
|
|
5021
|
+
const dialog = dialogRef.current;
|
|
5022
|
+
if (!dialog)
|
|
5023
|
+
return;
|
|
5024
|
+
if (isOpen && !dialog.open) {
|
|
5025
|
+
dialog.showModal();
|
|
5026
|
+
} else if (!isOpen && dialog.open) {
|
|
5027
|
+
dialog.close();
|
|
5028
|
+
}
|
|
5029
|
+
}, [isOpen]);
|
|
5030
|
+
const handleClose = q2(() => {
|
|
5031
|
+
debugState.isLoadDialogOpen.value = false;
|
|
5032
|
+
}, []);
|
|
5033
|
+
const handleFileSelect = q2(async (file) => {
|
|
5034
|
+
if (!file.name.endsWith(".bloop"))
|
|
5035
|
+
return;
|
|
5036
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
5037
|
+
debugState.onLoadTape.value?.(bytes, file.name);
|
|
5038
|
+
}, []);
|
|
5039
|
+
const handleDropZoneClick = q2(() => {
|
|
5040
|
+
fileInputRef.current?.click();
|
|
5041
|
+
}, []);
|
|
5042
|
+
const handleFileInputChange = q2((e4) => {
|
|
5043
|
+
const input = e4.currentTarget;
|
|
5044
|
+
const file = input.files?.[0];
|
|
5045
|
+
if (file) {
|
|
5046
|
+
handleFileSelect(file);
|
|
5047
|
+
input.value = "";
|
|
5048
|
+
}
|
|
5049
|
+
}, [handleFileSelect]);
|
|
5050
|
+
const handleDragOver = q2((e4) => {
|
|
5051
|
+
e4.preventDefault();
|
|
5052
|
+
if (e4.dataTransfer)
|
|
5053
|
+
e4.dataTransfer.dropEffect = "copy";
|
|
5054
|
+
setIsDragOver(true);
|
|
5055
|
+
}, []);
|
|
5056
|
+
const handleDragLeave = q2(() => {
|
|
5057
|
+
setIsDragOver(false);
|
|
5058
|
+
}, []);
|
|
5059
|
+
const handleDrop = q2((e4) => {
|
|
5060
|
+
e4.preventDefault();
|
|
5061
|
+
setIsDragOver(false);
|
|
5062
|
+
const file = e4.dataTransfer?.files[0];
|
|
5063
|
+
if (file) {
|
|
5064
|
+
handleFileSelect(file);
|
|
5065
|
+
}
|
|
5066
|
+
}, [handleFileSelect]);
|
|
5067
|
+
const handleReplayLast = q2(() => {
|
|
5068
|
+
debugState.onReplayLastTape.value?.();
|
|
5069
|
+
}, []);
|
|
5070
|
+
return /* @__PURE__ */ u4("dialog", {
|
|
5071
|
+
ref: dialogRef,
|
|
5072
|
+
className: "load-tape-dialog",
|
|
5073
|
+
onClose: handleClose,
|
|
5074
|
+
children: /* @__PURE__ */ u4("div", {
|
|
5075
|
+
className: "load-tape-dialog-content",
|
|
5076
|
+
children: [
|
|
5077
|
+
/* @__PURE__ */ u4("h3", {
|
|
5078
|
+
children: "Load Tape"
|
|
5079
|
+
}, undefined, false, undefined, this),
|
|
5080
|
+
/* @__PURE__ */ u4("div", {
|
|
5081
|
+
className: `drop-zone ${isDragOver ? "drag-over" : ""}`,
|
|
5082
|
+
onClick: handleDropZoneClick,
|
|
5083
|
+
onDragOver: handleDragOver,
|
|
5084
|
+
onDragLeave: handleDragLeave,
|
|
5085
|
+
onDrop: handleDrop,
|
|
5086
|
+
children: /* @__PURE__ */ u4("span", {
|
|
5087
|
+
className: "drop-zone-text",
|
|
5088
|
+
children: [
|
|
5089
|
+
"Drop .bloop file here",
|
|
5090
|
+
/* @__PURE__ */ u4("br", {}, undefined, false, undefined, this),
|
|
5091
|
+
"or click to browse"
|
|
5092
|
+
]
|
|
5093
|
+
}, undefined, true, undefined, this)
|
|
5094
|
+
}, undefined, false, undefined, this),
|
|
5095
|
+
/* @__PURE__ */ u4("input", {
|
|
5096
|
+
ref: fileInputRef,
|
|
5097
|
+
type: "file",
|
|
5098
|
+
accept: ".bloop",
|
|
5099
|
+
className: "hidden-file-input",
|
|
5100
|
+
onChange: handleFileInputChange
|
|
5101
|
+
}, undefined, false, undefined, this),
|
|
5102
|
+
lastTapeName2 && /* @__PURE__ */ u4("button", {
|
|
5103
|
+
className: "replay-last-btn",
|
|
5104
|
+
onClick: handleReplayLast,
|
|
5105
|
+
children: [
|
|
5106
|
+
"Replay last: ",
|
|
5107
|
+
lastTapeName2
|
|
5108
|
+
]
|
|
5109
|
+
}, undefined, true, undefined, this)
|
|
5110
|
+
]
|
|
5111
|
+
}, undefined, true, undefined, this)
|
|
5112
|
+
}, undefined, false, undefined, this);
|
|
5113
|
+
}
|
|
5114
|
+
|
|
4892
5115
|
// src/debugui/components/BottomBar.tsx
|
|
4893
5116
|
function useRepeatOnHold(action) {
|
|
4894
5117
|
const rafId = A2(null);
|
|
@@ -4975,6 +5198,12 @@ function BottomBar() {
|
|
|
4975
5198
|
debugState.onSeek.value?.(ratio);
|
|
4976
5199
|
}, []);
|
|
4977
5200
|
const seekDrag = useSeekDrag(handleSeek);
|
|
5201
|
+
const handleLoadTapeClick = q2(() => {
|
|
5202
|
+
debugState.isLoadDialogOpen.value = true;
|
|
5203
|
+
}, []);
|
|
5204
|
+
const handleSaveTapeClick = q2(() => {
|
|
5205
|
+
debugState.onSaveTape.value?.();
|
|
5206
|
+
}, []);
|
|
4978
5207
|
return /* @__PURE__ */ u4("div", {
|
|
4979
5208
|
className: "bottom-bar",
|
|
4980
5209
|
children: [
|
|
@@ -4982,7 +5211,7 @@ function BottomBar() {
|
|
|
4982
5211
|
className: "playbar-controls",
|
|
4983
5212
|
children: [
|
|
4984
5213
|
/* @__PURE__ */ u4("button", {
|
|
4985
|
-
className: "playbar-btn",
|
|
5214
|
+
className: "playbar-btn jump-back",
|
|
4986
5215
|
...jumpBackRepeat,
|
|
4987
5216
|
children: [
|
|
4988
5217
|
"<<",
|
|
@@ -4998,7 +5227,7 @@ function BottomBar() {
|
|
|
4998
5227
|
]
|
|
4999
5228
|
}, undefined, true, undefined, this),
|
|
5000
5229
|
/* @__PURE__ */ u4("button", {
|
|
5001
|
-
className: "playbar-btn",
|
|
5230
|
+
className: "playbar-btn step-back",
|
|
5002
5231
|
...stepBackRepeat,
|
|
5003
5232
|
children: [
|
|
5004
5233
|
"<",
|
|
@@ -5014,7 +5243,7 @@ function BottomBar() {
|
|
|
5014
5243
|
]
|
|
5015
5244
|
}, undefined, true, undefined, this),
|
|
5016
5245
|
/* @__PURE__ */ u4("button", {
|
|
5017
|
-
className: "playbar-btn",
|
|
5246
|
+
className: "playbar-btn play-pause",
|
|
5018
5247
|
onClick: handlePlayPause,
|
|
5019
5248
|
children: [
|
|
5020
5249
|
isPlaying2 ? "||" : ">",
|
|
@@ -5031,7 +5260,7 @@ function BottomBar() {
|
|
|
5031
5260
|
]
|
|
5032
5261
|
}, undefined, true, undefined, this),
|
|
5033
5262
|
/* @__PURE__ */ u4("button", {
|
|
5034
|
-
className: "playbar-btn",
|
|
5263
|
+
className: "playbar-btn step-forward",
|
|
5035
5264
|
...stepForwardRepeat,
|
|
5036
5265
|
children: [
|
|
5037
5266
|
">",
|
|
@@ -5047,7 +5276,7 @@ function BottomBar() {
|
|
|
5047
5276
|
]
|
|
5048
5277
|
}, undefined, true, undefined, this),
|
|
5049
5278
|
/* @__PURE__ */ u4("button", {
|
|
5050
|
-
className: "playbar-btn",
|
|
5279
|
+
className: "playbar-btn jump-forward",
|
|
5051
5280
|
...jumpForwardRepeat,
|
|
5052
5281
|
children: [
|
|
5053
5282
|
">>",
|
|
@@ -5061,6 +5290,33 @@ function BottomBar() {
|
|
|
5061
5290
|
]
|
|
5062
5291
|
}, undefined, true, undefined, this)
|
|
5063
5292
|
]
|
|
5293
|
+
}, undefined, true, undefined, this),
|
|
5294
|
+
/* @__PURE__ */ u4("button", {
|
|
5295
|
+
className: "playbar-btn save-tape-btn",
|
|
5296
|
+
onClick: handleSaveTapeClick,
|
|
5297
|
+
children: [
|
|
5298
|
+
"Save",
|
|
5299
|
+
/* @__PURE__ */ u4("span", {
|
|
5300
|
+
className: "tooltip",
|
|
5301
|
+
children: [
|
|
5302
|
+
"Save tape ",
|
|
5303
|
+
/* @__PURE__ */ u4("kbd", {
|
|
5304
|
+
children: "Cmd+S"
|
|
5305
|
+
}, undefined, false, undefined, this)
|
|
5306
|
+
]
|
|
5307
|
+
}, undefined, true, undefined, this)
|
|
5308
|
+
]
|
|
5309
|
+
}, undefined, true, undefined, this),
|
|
5310
|
+
/* @__PURE__ */ u4("button", {
|
|
5311
|
+
className: "playbar-btn load-tape-btn",
|
|
5312
|
+
onClick: handleLoadTapeClick,
|
|
5313
|
+
children: [
|
|
5314
|
+
"Load",
|
|
5315
|
+
/* @__PURE__ */ u4("span", {
|
|
5316
|
+
className: "tooltip",
|
|
5317
|
+
children: "Load tape"
|
|
5318
|
+
}, undefined, false, undefined, this)
|
|
5319
|
+
]
|
|
5064
5320
|
}, undefined, true, undefined, this)
|
|
5065
5321
|
]
|
|
5066
5322
|
}, undefined, true, undefined, this),
|
|
@@ -5077,7 +5333,8 @@ function BottomBar() {
|
|
|
5077
5333
|
style: { left: `${playheadPosition2 * tapeUtilization2 * 100}%` }
|
|
5078
5334
|
}, undefined, false, undefined, this)
|
|
5079
5335
|
]
|
|
5080
|
-
}, undefined, true, undefined, this)
|
|
5336
|
+
}, undefined, true, undefined, this),
|
|
5337
|
+
/* @__PURE__ */ u4(LoadTapeDialog, {}, undefined, false, undefined, this)
|
|
5081
5338
|
]
|
|
5082
5339
|
}, undefined, true, undefined, this);
|
|
5083
5340
|
}
|
|
@@ -5203,10 +5460,26 @@ var styles = `
|
|
|
5203
5460
|
box-sizing: border-box;
|
|
5204
5461
|
}
|
|
5205
5462
|
|
|
5463
|
+
/* Mobile-first CSS variables */
|
|
5464
|
+
:host {
|
|
5465
|
+
--bar-size: 10vw;
|
|
5466
|
+
--bar-size-h: 10vh;
|
|
5467
|
+
--bar-size-h: 10dvh;
|
|
5468
|
+
}
|
|
5469
|
+
|
|
5470
|
+
/* Desktop overrides */
|
|
5471
|
+
@media (min-width: 769px) {
|
|
5472
|
+
:host {
|
|
5473
|
+
--bar-size: 2vw;
|
|
5474
|
+
--bar-size-h: 2vh;
|
|
5475
|
+
}
|
|
5476
|
+
}
|
|
5477
|
+
|
|
5206
5478
|
/* Layout */
|
|
5207
5479
|
.fullscreen {
|
|
5208
5480
|
width: 100vw;
|
|
5209
5481
|
height: 100vh;
|
|
5482
|
+
height: 100dvh;
|
|
5210
5483
|
margin: 0;
|
|
5211
5484
|
padding: 0;
|
|
5212
5485
|
overflow: hidden;
|
|
@@ -5223,17 +5496,96 @@ var styles = `
|
|
|
5223
5496
|
display: block;
|
|
5224
5497
|
}
|
|
5225
5498
|
|
|
5499
|
+
/* Mobile-first: vertical scroll layout */
|
|
5226
5500
|
.layout {
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5501
|
+
/* Use fixed position on mobile to escape parent overflow:hidden */
|
|
5502
|
+
position: fixed;
|
|
5503
|
+
top: 0;
|
|
5504
|
+
left: 0;
|
|
5505
|
+
right: 0;
|
|
5506
|
+
bottom: 0;
|
|
5507
|
+
display: flex;
|
|
5508
|
+
flex-direction: column;
|
|
5509
|
+
overflow-y: auto;
|
|
5510
|
+
overflow-x: hidden;
|
|
5511
|
+
-webkit-overflow-scrolling: touch;
|
|
5512
|
+
overscroll-behavior-y: contain;
|
|
5513
|
+
padding: 0;
|
|
5514
|
+
gap: 0;
|
|
5515
|
+
background: #1a1a1a;
|
|
5516
|
+
}
|
|
5517
|
+
|
|
5518
|
+
.layout .game {
|
|
5519
|
+
/* Use dvh with vh fallback for mobile Safari address bar */
|
|
5520
|
+
height: 100vh;
|
|
5521
|
+
height: 100dvh;
|
|
5522
|
+
width: 100%;
|
|
5523
|
+
flex-shrink: 0;
|
|
5524
|
+
/* Mobile: no border radius, fullscreen game */
|
|
5525
|
+
border-radius: 0;
|
|
5526
|
+
}
|
|
5527
|
+
|
|
5528
|
+
/* Mobile: stretch canvas to fill game area */
|
|
5529
|
+
.layout .game .canvas-container {
|
|
5530
|
+
width: 100%;
|
|
5531
|
+
height: 100%;
|
|
5532
|
+
}
|
|
5533
|
+
|
|
5534
|
+
.layout .game .canvas-container canvas {
|
|
5234
5535
|
width: 100%;
|
|
5235
5536
|
height: 100%;
|
|
5537
|
+
max-width: none;
|
|
5538
|
+
max-height: none;
|
|
5539
|
+
display: block;
|
|
5540
|
+
}
|
|
5541
|
+
|
|
5542
|
+
.layout .stats,
|
|
5543
|
+
.layout .logs {
|
|
5544
|
+
width: 100%;
|
|
5545
|
+
min-height: 50vh;
|
|
5546
|
+
min-height: 50dvh;
|
|
5236
5547
|
padding: 1rem;
|
|
5548
|
+
flex-shrink: 0;
|
|
5549
|
+
}
|
|
5550
|
+
|
|
5551
|
+
/* Desktop: 2x2 grid layout */
|
|
5552
|
+
@media (min-width: 769px) {
|
|
5553
|
+
.layout {
|
|
5554
|
+
position: static;
|
|
5555
|
+
display: grid;
|
|
5556
|
+
grid-template-areas:
|
|
5557
|
+
"game stats"
|
|
5558
|
+
"logs logs";
|
|
5559
|
+
grid-template-columns: calc(50% - 0.5rem) calc(50% - 0.5rem);
|
|
5560
|
+
grid-template-rows: calc(50% - 0.5rem) calc(50% - 0.5rem);
|
|
5561
|
+
gap: 1rem;
|
|
5562
|
+
padding: 1rem;
|
|
5563
|
+
height: 100%;
|
|
5564
|
+
overflow: hidden;
|
|
5565
|
+
-webkit-overflow-scrolling: auto;
|
|
5566
|
+
overscroll-behavior-y: auto;
|
|
5567
|
+
}
|
|
5568
|
+
|
|
5569
|
+
.layout .game {
|
|
5570
|
+
height: auto;
|
|
5571
|
+
flex-shrink: initial;
|
|
5572
|
+
border-radius: 8px;
|
|
5573
|
+
}
|
|
5574
|
+
|
|
5575
|
+
/* Desktop: restore centered canvas with constraints */
|
|
5576
|
+
.layout .game .canvas-container canvas {
|
|
5577
|
+
width: auto;
|
|
5578
|
+
height: auto;
|
|
5579
|
+
max-width: 100%;
|
|
5580
|
+
max-height: 100%;
|
|
5581
|
+
}
|
|
5582
|
+
|
|
5583
|
+
.layout .stats,
|
|
5584
|
+
.layout .logs {
|
|
5585
|
+
min-height: auto;
|
|
5586
|
+
padding: 1rem;
|
|
5587
|
+
flex-shrink: initial;
|
|
5588
|
+
}
|
|
5237
5589
|
}
|
|
5238
5590
|
|
|
5239
5591
|
/* Letterboxed layout - using equal vw/vh percentages keeps game at viewport aspect ratio */
|
|
@@ -5243,10 +5595,12 @@ var styles = `
|
|
|
5243
5595
|
"top-bar top-bar top-bar"
|
|
5244
5596
|
"left-bar game right-bar"
|
|
5245
5597
|
"bottom-bar bottom-bar bottom-bar";
|
|
5246
|
-
grid-template-columns:
|
|
5247
|
-
grid-template-rows:
|
|
5598
|
+
grid-template-columns: var(--bar-size) 1fr var(--bar-size);
|
|
5599
|
+
grid-template-rows: var(--bar-size-h) 1fr var(--bar-size-h);
|
|
5248
5600
|
width: 100vw;
|
|
5601
|
+
/* Use dvh with vh fallback for mobile Safari address bar */
|
|
5249
5602
|
height: 100vh;
|
|
5603
|
+
height: 100dvh;
|
|
5250
5604
|
background: #1a1a1a;
|
|
5251
5605
|
overflow: hidden;
|
|
5252
5606
|
overscroll-behavior: none;
|
|
@@ -5265,7 +5619,7 @@ var styles = `
|
|
|
5265
5619
|
}
|
|
5266
5620
|
|
|
5267
5621
|
.top-bar-side-label {
|
|
5268
|
-
width:
|
|
5622
|
+
width: var(--bar-size);
|
|
5269
5623
|
text-align: center;
|
|
5270
5624
|
font-size: 9px;
|
|
5271
5625
|
text-transform: uppercase;
|
|
@@ -5273,6 +5627,17 @@ var styles = `
|
|
|
5273
5627
|
color: #666;
|
|
5274
5628
|
}
|
|
5275
5629
|
|
|
5630
|
+
/* Mobile: larger top bar text */
|
|
5631
|
+
@media (max-width: 768px) {
|
|
5632
|
+
.top-bar-side-label {
|
|
5633
|
+
font-size: 12px;
|
|
5634
|
+
}
|
|
5635
|
+
|
|
5636
|
+
.top-bar {
|
|
5637
|
+
font-size: 14px;
|
|
5638
|
+
}
|
|
5639
|
+
}
|
|
5640
|
+
|
|
5276
5641
|
.top-bar-center {
|
|
5277
5642
|
display: flex;
|
|
5278
5643
|
align-items: center;
|
|
@@ -5341,8 +5706,17 @@ var styles = `
|
|
|
5341
5706
|
display: flex;
|
|
5342
5707
|
align-items: center;
|
|
5343
5708
|
background: #111;
|
|
5344
|
-
|
|
5345
|
-
|
|
5709
|
+
/* Mobile-first: more padding */
|
|
5710
|
+
padding: 0 16px;
|
|
5711
|
+
gap: 12px;
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5714
|
+
/* Desktop: tighter padding */
|
|
5715
|
+
@media (min-width: 769px) {
|
|
5716
|
+
.bottom-bar {
|
|
5717
|
+
padding: 0 8px;
|
|
5718
|
+
gap: 8px;
|
|
5719
|
+
}
|
|
5346
5720
|
}
|
|
5347
5721
|
|
|
5348
5722
|
.playbar-controls {
|
|
@@ -5352,16 +5726,35 @@ var styles = `
|
|
|
5352
5726
|
flex-shrink: 0;
|
|
5353
5727
|
}
|
|
5354
5728
|
|
|
5729
|
+
/* Mobile-first: hide step/jump buttons */
|
|
5730
|
+
.playbar-btn.jump-back,
|
|
5731
|
+
.playbar-btn.step-back,
|
|
5732
|
+
.playbar-btn.step-forward,
|
|
5733
|
+
.playbar-btn.jump-forward {
|
|
5734
|
+
display: none;
|
|
5735
|
+
}
|
|
5736
|
+
|
|
5737
|
+
/* Desktop: show all controls */
|
|
5738
|
+
@media (min-width: 769px) {
|
|
5739
|
+
.playbar-btn.jump-back,
|
|
5740
|
+
.playbar-btn.step-back,
|
|
5741
|
+
.playbar-btn.step-forward,
|
|
5742
|
+
.playbar-btn.jump-forward {
|
|
5743
|
+
display: flex;
|
|
5744
|
+
}
|
|
5745
|
+
}
|
|
5746
|
+
|
|
5355
5747
|
.playbar-btn {
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
min-
|
|
5748
|
+
/* Mobile-first: larger buttons */
|
|
5749
|
+
width: 4vh;
|
|
5750
|
+
height: 4vh;
|
|
5751
|
+
min-width: 32px;
|
|
5752
|
+
min-height: 32px;
|
|
5360
5753
|
border: none;
|
|
5361
5754
|
outline: none;
|
|
5362
5755
|
background: transparent;
|
|
5363
5756
|
color: #888;
|
|
5364
|
-
font-size:
|
|
5757
|
+
font-size: 16px;
|
|
5365
5758
|
cursor: pointer;
|
|
5366
5759
|
border-radius: 2px;
|
|
5367
5760
|
display: flex;
|
|
@@ -5371,6 +5764,17 @@ var styles = `
|
|
|
5371
5764
|
position: relative;
|
|
5372
5765
|
}
|
|
5373
5766
|
|
|
5767
|
+
/* Desktop: smaller buttons */
|
|
5768
|
+
@media (min-width: 769px) {
|
|
5769
|
+
.playbar-btn {
|
|
5770
|
+
width: 1.5vh;
|
|
5771
|
+
height: 1.5vh;
|
|
5772
|
+
min-width: 18px;
|
|
5773
|
+
min-height: 18px;
|
|
5774
|
+
font-size: 10px;
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
|
|
5374
5778
|
.playbar-btn:hover {
|
|
5375
5779
|
background: #333;
|
|
5376
5780
|
color: #fff;
|
|
@@ -5414,7 +5818,8 @@ var styles = `
|
|
|
5414
5818
|
|
|
5415
5819
|
.seek-bar {
|
|
5416
5820
|
flex: 1;
|
|
5417
|
-
|
|
5821
|
+
/* Mobile-first: larger seek bar */
|
|
5822
|
+
height: 32px;
|
|
5418
5823
|
background: #222;
|
|
5419
5824
|
border-radius: 4px;
|
|
5420
5825
|
position: relative;
|
|
@@ -5422,6 +5827,13 @@ var styles = `
|
|
|
5422
5827
|
overflow: hidden;
|
|
5423
5828
|
}
|
|
5424
5829
|
|
|
5830
|
+
/* Desktop: smaller seek bar */
|
|
5831
|
+
@media (min-width: 769px) {
|
|
5832
|
+
.seek-bar {
|
|
5833
|
+
height: 16px;
|
|
5834
|
+
}
|
|
5835
|
+
}
|
|
5836
|
+
|
|
5425
5837
|
.seek-bar-fill {
|
|
5426
5838
|
position: absolute;
|
|
5427
5839
|
top: 0;
|
|
@@ -5644,6 +6056,89 @@ var styles = `
|
|
|
5644
6056
|
border-radius: 4px;
|
|
5645
6057
|
border: 1px inset lavender;
|
|
5646
6058
|
}
|
|
6059
|
+
|
|
6060
|
+
/* Load Tape Dialog */
|
|
6061
|
+
.load-tape-dialog {
|
|
6062
|
+
background: #1a1a1a;
|
|
6063
|
+
border: 1px solid #333;
|
|
6064
|
+
border-radius: 8px;
|
|
6065
|
+
padding: 0;
|
|
6066
|
+
color: #ccc;
|
|
6067
|
+
font-family: monospace;
|
|
6068
|
+
max-width: 320px;
|
|
6069
|
+
width: 90vw;
|
|
6070
|
+
}
|
|
6071
|
+
|
|
6072
|
+
.load-tape-dialog::backdrop {
|
|
6073
|
+
background: rgba(0, 0, 0, 0.7);
|
|
6074
|
+
}
|
|
6075
|
+
|
|
6076
|
+
.load-tape-dialog-content {
|
|
6077
|
+
padding: 16px;
|
|
6078
|
+
}
|
|
6079
|
+
|
|
6080
|
+
.load-tape-dialog h3 {
|
|
6081
|
+
margin: 0 0 16px 0;
|
|
6082
|
+
font-size: 14px;
|
|
6083
|
+
font-weight: 600;
|
|
6084
|
+
color: #fff;
|
|
6085
|
+
}
|
|
6086
|
+
|
|
6087
|
+
.drop-zone {
|
|
6088
|
+
border: 2px dashed #444;
|
|
6089
|
+
border-radius: 8px;
|
|
6090
|
+
padding: 32px 16px;
|
|
6091
|
+
text-align: center;
|
|
6092
|
+
cursor: pointer;
|
|
6093
|
+
transition: border-color 0.15s, background 0.15s;
|
|
6094
|
+
}
|
|
6095
|
+
|
|
6096
|
+
.drop-zone:hover {
|
|
6097
|
+
border-color: #666;
|
|
6098
|
+
background: #222;
|
|
6099
|
+
}
|
|
6100
|
+
|
|
6101
|
+
.drop-zone.drag-over {
|
|
6102
|
+
border-color: #7b3fa0;
|
|
6103
|
+
background: rgba(123, 63, 160, 0.1);
|
|
6104
|
+
}
|
|
6105
|
+
|
|
6106
|
+
.drop-zone-text {
|
|
6107
|
+
color: #888;
|
|
6108
|
+
font-size: 12px;
|
|
6109
|
+
line-height: 1.5;
|
|
6110
|
+
}
|
|
6111
|
+
|
|
6112
|
+
.hidden-file-input {
|
|
6113
|
+
display: none;
|
|
6114
|
+
}
|
|
6115
|
+
|
|
6116
|
+
.replay-last-btn {
|
|
6117
|
+
width: 100%;
|
|
6118
|
+
margin-top: 12px;
|
|
6119
|
+
padding: 8px 12px;
|
|
6120
|
+
background: #333;
|
|
6121
|
+
border: none;
|
|
6122
|
+
border-radius: 4px;
|
|
6123
|
+
color: #ccc;
|
|
6124
|
+
font-family: monospace;
|
|
6125
|
+
font-size: 12px;
|
|
6126
|
+
cursor: pointer;
|
|
6127
|
+
transition: background 0.15s;
|
|
6128
|
+
text-align: left;
|
|
6129
|
+
overflow: hidden;
|
|
6130
|
+
text-overflow: ellipsis;
|
|
6131
|
+
white-space: nowrap;
|
|
6132
|
+
}
|
|
6133
|
+
|
|
6134
|
+
.replay-last-btn:hover {
|
|
6135
|
+
background: #444;
|
|
6136
|
+
color: #fff;
|
|
6137
|
+
}
|
|
6138
|
+
|
|
6139
|
+
.load-tape-btn {
|
|
6140
|
+
margin-left: 4px;
|
|
6141
|
+
}
|
|
5647
6142
|
`;
|
|
5648
6143
|
|
|
5649
6144
|
// src/debugui/DebugUi.ts
|
|
@@ -6671,6 +7166,7 @@ class App {
|
|
|
6671
7166
|
this.#debugUi = new DebugUi(opts);
|
|
6672
7167
|
wirePlaybarHandlers(this);
|
|
6673
7168
|
wireTapeDragDrop(this.#debugUi.canvas, this);
|
|
7169
|
+
wireTapeLoadHandlers(this);
|
|
6674
7170
|
return this.#debugUi;
|
|
6675
7171
|
}
|
|
6676
7172
|
get debugUi() {
|
|
@@ -6954,5 +7450,5 @@ export {
|
|
|
6954
7450
|
App
|
|
6955
7451
|
};
|
|
6956
7452
|
|
|
6957
|
-
//# debugId=
|
|
7453
|
+
//# debugId=B02D4DB9DDB2D5FC64756E2164756E21
|
|
6958
7454
|
//# sourceMappingURL=mod.js.map
|