Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

cap/video: route camera diags + swap → top-right TextButton + back resets state

cap.mjs:
- Replace the custom SwapButton (bottom-right) with a real
ui.TextButton anchored top-right. Matches the rest of the app's
button styling and keeps the bottom edge of the screen clear for
the hold-to-record gesture. Box hit-test for the touch handler now
goes through swapBtn.btn.box.contains(e).

video.mjs:
- Back button now properly slates the recording AND resets the local
playback / export / scrub state on its way out. Without this, the
in-flight tapeProgress bar, scrub strip, and post button kept
drawing over a fresh cap session after the user hit Back.

disk.mjs:
- Route camera:debug and camera:debug:frame messages from bios.mjs
directly to console.log inside the worker. The actAlerts queue
only carries string keys, so these typed payloads were getting
dropped before reaching cap.mjs's act() handler — which is why
no cam/init / cam/frame events were showing up in piece-runs.
Now they flow through to MongoDB and we can see what iOS actually
hands back.

+67 -7
+10 -5
system/public/aesthetic.computer/disks/cap.mjs
··· 20 20 #endregion */ 21 21 22 22 import { 23 - SwapButton, 24 23 RecordingTimer, 25 24 MicLevel, 26 25 sounds, ··· 82 81 rec, 83 82 painting, 84 83 recordingUI, 84 + ui, 85 85 num: { randIntRange, clamp, rand }, 86 86 }) { 87 87 // Initialize video feed to match screen dimensions (not painting) ··· 127 127 const centerX = floor(screen.width / 2); 128 128 const bottomY = screen.height - 28; 129 129 130 - // Swap button (bottom right, only if multiple cameras and not recording) 130 + // Swap-camera TextButton, top-right. Only shown when multiple cameras 131 + // are available and we're not actively (or about to be) recording. 132 + // Lives in the recordingUI overlay so it isn't baked into the tape, 133 + // and is anchored top-right so the bottom edge stays clear for the 134 + // hold-to-record gesture. 131 135 if (cameras > 1 && !isRecording && !pendingRecordStart) { 132 136 if (!swapBtn) { 133 - swapBtn = new SwapButton({ x: 0, y: 0, width: 48, height: 20 }); 137 + swapBtn = new ui.TextButton("Swap", { right: 6, top: 6, screen }); 138 + swapBtn.btn.stickyScrubbing = true; 134 139 } 135 - swapBtn.reposition({ right: 6, bottom: 6, screen }); 140 + swapBtn.reposition({ right: 6, top: 6, screen }, "Swap"); 136 141 swapBtn.paint($); 137 142 } 138 143 ··· 328 333 // 🎬 Hold-to-record (BakTok pattern): touch anywhere outside the swap 329 334 // button or HUD label starts recording; releasing stops + jumps to video. 330 335 if (e.is("touch") && !leaving()) { 331 - const onSwapBtn = swapBtn?.contains(e.x, e.y); 336 + const onSwapBtn = swapBtn?.btn?.box?.contains(e); 332 337 const onHud = hud?.currentLabel()?.btn?.down; 333 338 if (!onSwapBtn && !onHud && !isRecording && !pendingRecordStart) { 334 339 startRecording(rec, sound, notice);
+44 -2
system/public/aesthetic.computer/disks/video.mjs
··· 827 827 volume: 0.5, 828 828 duration: 0.005, 829 829 }); 830 - // Drop the current tape so cap.mjs starts clean. 831 - rec?.slate?.(); 830 + // Drop the current tape and any cached export / playback state 831 + // so cap.mjs starts clean and stale UI (progress bar, scrub 832 + // strip, post button) doesn't bleed through to the next visit. 833 + try { 834 + rec?.slate?.(); 835 + if (rec) { 836 + rec.tapeProgress = 0; 837 + rec.printing = false; 838 + rec.presenting = false; 839 + rec.recorded = false; 840 + rec.presentProgress = 0; 841 + } 842 + } catch {} 843 + isPrinting = false; 844 + isPostingTape = false; 845 + isExportingGIF = false; 846 + isExportingFrames = false; 847 + isExportingWebP = false; 848 + isExportingAnimWebP = false; 849 + isExportingAPNG = false; 850 + currentExportType = ""; 851 + currentExportPhase = ""; 852 + exportStatusMessage = ""; 853 + printProgress = 0; 854 + progressHistory = []; 855 + exportStartTime = 0; 856 + completionMessage = ""; 857 + completionMessageTimer = 0; 858 + postedTapeCode = null; 859 + tapeInfo = null; 860 + isScrubbing = false; 861 + inertiaActive = false; 862 + scrubSpeed = 0; 863 + scrubMoved = false; 864 + scrubCurrentProgress = 0; 865 + scrubAudioSpeed = 1; 866 + wasPlayingBeforeScrub = false; 867 + tapeWaveform = null; 868 + scrubStripBtn = null; 869 + backBtn = undefined; 870 + postBtn = undefined; 871 + gifBtn = undefined; 872 + mp4Btn = undefined; 873 + zipBtn = undefined; 832 874 jump("cap"); 833 875 }, 834 876 });
+13
system/public/aesthetic.computer/lib/disk.mjs
··· 11491 11491 return; 11492 11492 } 11493 11493 11494 + // 📊 Camera diagnostics from bios — log directly here so they land in 11495 + // the piece-runs silo via the patched console. Avoids needing to wire 11496 + // every diagnostic type into the actAlerts queue (which only carries 11497 + // string keys, not the full content payload we need for debugging). 11498 + if (type === "camera:debug" || type === "camera:debug:frame") { 11499 + try { 11500 + console.log(`📷 ${type}:`, JSON.stringify(content)); 11501 + } catch { 11502 + console.log(`📷 ${type}:`, content); 11503 + } 11504 + return; 11505 + } 11506 + 11494 11507 // 1c. Loading from History 11495 11508 if (type === "history-load") { 11496 11509 if (debug && logs.history) console.log("⏳ History:", content);