diff --git a/GRAVEYARD.txt b/GRAVEYARD.txt index 59dd989a4b..176e40c380 100644 --- a/GRAVEYARD.txt +++ b/GRAVEYARD.txt @@ -1,7 +1,21 @@ ๐Ÿชฆ Completed Tasks (dumped from `README.txt`) - - [x] Fix regional text selection delay support. - - [x] immediate first key entry no longer works. +*** text entry regressions *** + + Done + - [x] Fix regional text selection delay support. + - [x] immediate first key entry no longer works. + - [x] Clear response highlighted text. + - [x] NETWORK FAILURE does not reset the text. + - [x] Backspace shortcut. + - [x] `prompt~line` shortcut no longer works... + - [x] sounds no longer function + - [x] starting with left or right arrow keys doesn't clear prompt + - [x] Pressing tilde while processing can be weird, and + so can typing while processing. + - [x] moving arrow keys left and right... + +*** `wave` *** + - [x] `wave` pixels are still stretched on Android. *** landing page *** + Done diff --git a/README.txt b/README.txt index 713b2a7fdd..07dbd3ff83 100644 --- a/README.txt +++ b/README.txt @@ -40,11 +40,8 @@ ๐ŸŒŸ Projects in Progress (PIP) ๐ŸŒŸ -*** text entry regressions *** - - [๐Ÿงก] Backspace shortcut. - - [] Pressing tilde while processing can be weird, and - so can typing while processing. - - [] `prompt~line` shortcut no longer works... +*** `bb` -> `booted-by` *** + - [] make bb a short name for booted-by *** `moods` *** - [-] Show a live-updated list of user moods diff --git a/system/backend/database.mjs b/system/backend/database.mjs index 32ff97e6d2..c10a88e391 100644 --- a/system/backend/database.mjs +++ b/system/backend/database.mjs @@ -21,7 +21,7 @@ async function connect() { } async function disconnect() { - await client?.close(); + await client?.close?.(); } // Re-usable calls to the application. diff --git a/system/public/aesthetic.computer/bios.mjs b/system/public/aesthetic.computer/bios.mjs index 990aa12990..2bb8aa11b8 100644 --- a/system/public/aesthetic.computer/bios.mjs +++ b/system/public/aesthetic.computer/bios.mjs @@ -1543,7 +1543,7 @@ async function boot(parsed, bpm = 60, resolution, debug) { } if (type === "bgm-change") { - playBackgroundMusic(content.trackNumber, content.volume); + playBackgroundMusic(content.trackNumber, content.volume || 1); return; } @@ -1576,30 +1576,30 @@ async function boot(parsed, bpm = 60, resolution, debug) { const form = document.createElement("form"); form.id = "software-keyboard-input-form"; form.style.opacity = 0; - // form.style.opacity = 1; input.style.position = "absolute"; - // input.style.top = "50px"; - // input.style.left = "0px"; - // input.style.zIndex = 100; - input.id = "software-keyboard-input"; - // input.type = "text"; input.autocapitalize = "none"; + // input.type = "text"; input.autocomplete = "off"; input.style.opacity = 0; - // input.style.opacity = 1; input.style.width = 0 + "px"; input.style.height = 0 + "px"; + + // ๐Ÿ““ Uncomment to debug text editing form synchronization. + // form.style.opacity = 1; + // input.style.zIndex = 100; + // input.style.top = "50px"; + // input.style.left = "0px"; + // input.style.opacity = 1; // input.style.width = 200 + "px"; // input.style.height = 50 + "px"; - // input.value = "_"; - form.append(input); wrapper.append(form); keyboard.focusHandler = function (e) { if (!currentPieceHasKeyboard) return; + if (keyboardFocusLock) return; if ( document.activeElement !== input && e.key !== "`" && @@ -1607,6 +1607,14 @@ async function boot(parsed, bpm = 60, resolution, debug) { ) { keyboardOpenMethod = "keyboard"; input.focus(); + + if (e.key.length !== 1 || e.ctrl) { + send({ + type: "prompt:text:replace", + content: { text: "", cursor: 0, mute: true }, + }); + } + return true; } else if (e.key === "Enter" && e.shiftKey === false) { // input.blur(); // Deprecated 23.07.29.17.44 @@ -1710,6 +1718,10 @@ async function boot(parsed, bpm = 60, resolution, debug) { // }); input.addEventListener("keydown", (e) => { + if (keyboardFocusLock) { + e.preventDefault(); + return; + } if (e.key === "ArrowLeft" || e.key === "ArrowRight") { let cursor = input.selectionDirection === "backward" @@ -2101,11 +2113,13 @@ async function boot(parsed, bpm = 60, resolution, debug) { } if (type === "keyboard:close") { + if (keyboardFocusLock) return; keyboard?.input.blur(); return; } if (type === "keyboard:open") { + if (keyboardFocusLock) return; currentPieceHasKeyboard = true; keyboard?.input.focus(); // if (keyboard) keyboard.needsImmediateOpen = true; // For iOS. @@ -4364,13 +4378,13 @@ async function boot(parsed, bpm = 60, resolution, debug) { function diagram(hand) { if (facingMode === "user") { - hand.screen.forEach((l) => (l.x = 1 - l.x)); + // hand.screen.forEach((l) => (l.x = 1 - l.x)); // Reverse handedness because our data is mirrored. - if (hand.handedness === "left") { - hand.handedness = "right"; - } else if (hand.handedness === "right") { - hand.handedness = "left"; - } + // if (hand.handedness === "left") { + // hand.handedness = "right"; + // } else if (hand.handedness === "right") { + // hand.handedness = "left"; + // } } handData = hand; } @@ -4382,12 +4396,24 @@ async function boot(parsed, bpm = 60, resolution, debug) { // TODO: Video effects / filter kernels could be added here... // ๐Ÿ’ก For GPU backed visuals. 23.04.29.20.47 + // Send frames by default. + if (facingMode === "user" || (!iOS && !Android)) { + bufferCtx.translate(buffer.width / 2, buffer.height / 2); + const zoom = 1; + // if (hands) { + // bufferCtx.scale(zoom, zoom); + // } else { + bufferCtx.scale(-zoom, zoom); + // } + bufferCtx.translate(-buffer.width / 2, -buffer.height / 2); + } + // ๐Ÿคš Track Hands on the GPU if flagged. if (hands === true && handAPI) { if (handVideoTime !== video.currentTime && video.videoWidth > 0) { handVideoTime = video.currentTime; if (useLegacyHandsAPI && !handAPI?.legacyProcessing) { - handAPI.hands?.send({ image: video }).then(() => { + handAPI.hands?.send({ image: bufferCtx.canvas }).then(() => { handAPI.legacyProcessing = false; // Don't process more than one frame at a time. }); @@ -4402,40 +4428,31 @@ async function boot(parsed, bpm = 60, resolution, debug) { } } - // Send frames by default. - if (options.hidden !== true) { - if (facingMode === "user" || (!iOS && !Android)) { - bufferCtx.translate(buffer.width / 2, buffer.height / 2); - const zoom = 1; - bufferCtx.scale(-zoom, zoom); - bufferCtx.translate(-buffer.width / 2, -buffer.height / 2); - } - - // Drawing a video frame to the buffer (mirrored, proportion adjusted). - const videoAR = video.videoWidth / video.videoHeight; - const bufferAR = buffer.width / buffer.height; - let outWidth, - outHeight, - outX = 0, - outY = 0; - - if (videoAR <= bufferAR) { - // Tall to wide. - outWidth = buffer.width; - outHeight = outWidth / videoAR; - } else { - // Wide to tall. - outHeight = buffer.height; - outWidth = outHeight * videoAR; - } - - outY = (buffer.height - outHeight) / 2; // Adjusting position. - outX = (buffer.width - outWidth) / 2; + // Drawing a video frame to the buffer (mirrored, proportion adjusted). + const videoAR = video.videoWidth / video.videoHeight; + const bufferAR = buffer.width / buffer.height; + let outWidth, + outHeight, + outX = 0, + outY = 0; + + if (videoAR <= bufferAR) { + // Tall to wide. + outWidth = buffer.width; + outHeight = outWidth / videoAR; + } else { + // Wide to tall. + outHeight = buffer.height; + outWidth = outHeight * videoAR; + } - bufferCtx.drawImage(video, outX, outY, outWidth, outHeight); + outY = (buffer.height - outHeight) / 2; // Adjusting position. + outX = (buffer.width - outWidth) / 2; - bufferCtx.resetTransform(); + bufferCtx.drawImage(video, outX, outY, outWidth, outHeight); + bufferCtx.resetTransform(); + if (options.hidden !== true) { const pixels = bufferCtx.getImageData( 0, 0, diff --git a/system/public/aesthetic.computer/disks/bgm.mjs b/system/public/aesthetic.computer/disks/bgm.mjs index 9c84df9352..3352a50fe5 100644 --- a/system/public/aesthetic.computer/disks/bgm.mjs +++ b/system/public/aesthetic.computer/disks/bgm.mjs @@ -2,7 +2,13 @@ // Play indexed background music and run a visualizer. /* #region ๐Ÿ todo + - [] Change bgm system to play via sfx and not + end when pieces change. + - [] Play from time:time - [] Two tracks meant to play together as a musical system. + Add support for multiple playing tracks. + - [] Add playback speed parameter. + - [] Fade tracks. - [] Add a clickable play button overlay if bgm is used as a landing page. - [] Draw a rasterized, filled triangle for the play button! - [] Draw thicker rasterized lines for the visualizer? @@ -11,19 +17,22 @@ - [] Radiate lines out from the center? #endregion */ -const trackCount = 17; // See `backgroundTrackURLs` in `bios.mjs`. +const trackCount = 17; // See `backgroundTrackURLs` in `bios.mjs`. +let setTrack; // ๐Ÿฅพ Boot (Runs once before first paint and sim) -function boot({ wipe, bgm, params, num }) { +function boot({ wipe, bgm, params, num, hud }) { params = params.map((str) => parseInt(str)) || 0; if (params.length === 0) params[0] = num.randInt(trackCount - 1); - bgm.set(params[0]); + setTrack = params[0] % trackCount; + bgm.set(setTrack, 0.5); + hud.label(`bgm ${setTrack}`); wipe(0, 0, 100); } // ๐ŸŽจ Paint (Executes every display frame) -function paint({ line, wipe, bgm, ink, screen }) { - wipe(bgm.data.amplitude); +function paint({ line, wipe, bgm, ink, screen, write }) { + wipe(bgm.data.amplitude || 127); let x = 0; bgm.data.sample.forEach((smp) => { @@ -31,6 +40,12 @@ function paint({ line, wipe, bgm, ink, screen }) { line(x, screen.height, x, screen.height - smp); x += 1; }); + + ink(255).write(setTrack, { x: 6 * 5, y: 6 }); + ink(0).write("by vacuum flowers", { + x: 6 * (6 + setTrack.toFixed().length), + y: 6, + }); } // ๐Ÿ“š Library (Useful functions used throughout the piece) diff --git a/system/public/aesthetic.computer/disks/prompt.mjs b/system/public/aesthetic.computer/disks/prompt.mjs index 5b96fd1f3c..9d3efd1d0f 100644 --- a/system/public/aesthetic.computer/disks/prompt.mjs +++ b/system/public/aesthetic.computer/disks/prompt.mjs @@ -117,7 +117,7 @@ async function boot({ handles = data.handles; }) .catch((err) => { - console.warn("Could not get handles:", err); + console.warn("๐Ÿ’ Could not get handle count."); }); // Boot starfield with a clear backdrop. @@ -157,11 +157,13 @@ async function boot({ } if (params[0]) { - const text = params[0].replaceAll("~", " "); + const text = params.join(" "); + // const text = params[0].replaceAll("~", " "); system.prompt.input.text = text; system.prompt.input.runnable = true; system.prompt.input.addUserText(text); system.prompt.input.snap(); + send({ type: "keyboard:text:replace", content: { text } }); } else { system.prompt.input.text = ""; } @@ -1232,10 +1234,20 @@ function act({ if (e.is("pasted:text")) firstActivation = false; - if (e.is("keyboard:down") && e.key !== "Enter") { - play(keyboardSfx, { volume: 0.2 + (num.randInt(100) / 100) * 0.4 }); + if ( + e.is("prompt:text:replace") && + !firstActivation && + system.prompt.input.canType + ) { + if (!e.mute) + play(keyboardSfx, { volume: 0.2 + (num.randInt(100) / 100) * 0.4 }); } + // if (e.is("keyboard:down") && e.key !== "Enter") { + // console.log("down key..."); + // play(keyboardSfx, { volume: 0.2 + (num.randInt(100) / 100) * 0.4 }); + // } + // ๐Ÿ’พ Piece / disk loading if (e.is("load-error")) { makeFlash(api, false); diff --git a/system/public/aesthetic.computer/lib/logs.mjs b/system/public/aesthetic.computer/lib/logs.mjs index 685ef21cb9..c4fe4b2db7 100644 --- a/system/public/aesthetic.computer/lib/logs.mjs +++ b/system/public/aesthetic.computer/lib/logs.mjs @@ -9,7 +9,7 @@ export const logs = { session: true, // Socket session. download: false, // Download progress, etc. (JSON) audio: false, - hid: false, + hid: true, painting: false, // System wallpaper / paint related logs. glaze: false, deps: false, // Dependency loading and injection. diff --git a/system/public/aesthetic.computer/lib/type.mjs b/system/public/aesthetic.computer/lib/type.mjs index ffb4c7c454..23fa3eda65 100644 --- a/system/public/aesthetic.computer/lib/type.mjs +++ b/system/public/aesthetic.computer/lib/type.mjs @@ -204,7 +204,7 @@ class TextInput { canType = false; - #autolock = true; + //#autolock = true; lock = false; #prompt; @@ -239,6 +239,7 @@ class TextInput { activate; // Hook to `activate` inside of act. activated; // Optional callback for when the the text input becomes // activated via pushing the Enter button or typing a key. + activatedOnce = true; backdropTouchOff = false; // Determines whether to activate the input // after tapping the backdrop. commandSentOnce = false; // ๐Ÿด @@ -251,7 +252,7 @@ class TextInput { options = { palette: undefined, font: font1, - autolock: true, + //autolock: true, wrap: "char", }, ) { @@ -272,7 +273,7 @@ class TextInput { } this.activated = options.activated; - this.#autolock = options.autolock; + //this.#autolock = options.autolock; this.didReset = options.didReset; const blockWidth = 6; @@ -355,13 +356,19 @@ class TextInput { // Run a command async run(store) { this.#prompt.snapTo(this.text); + this.submittedText = ""; await this.#execute(store); // Send a command. } // Set the text and reflow it. set text(str) { + if (str === this.#text) { + // console.warn("Redundant text"); + return; + } this.#text = str; this.flow(); + // console.log("๐Ÿ“ Setting text to:", str); } // Return the prompt. @@ -595,13 +602,13 @@ class TextInput { // console.log("๐Ÿ“š Stored prompt history:", store[key]); store.persist(this.key); // Persist the history stack across tabs. // ๐ŸŽ Process commands for a given context, passing the text input. - if (this.#autolock) this.lock = true; // TODO: This might be redundant now. 23.06.07.23.32 + //if (this.#autolock) this.lock = true; // TODO: This might be redundant now. 23.06.07.23.32 // this.#processingCommand = true; await this.#processCommand?.(this.text); // this.#processingCommand = false; this.commandSentOnce = true; // this.enter.btn.down = false; // Make sure the Enter button is released. - if (this.#autolock) this.lock = false; + //if (this.#autolock) this.lock = false; } // Clear the TextInput object and flip the cursor to ON. @@ -868,6 +875,7 @@ class TextInput { this.activate(this); $.send({ type: "keyboard:open" }); this.text = ""; + $.send({ type: "keyboard:text:replace", content: { text: "" } }); this.#prompt.cursor = { x: 0, y: 0 }; } @@ -1038,7 +1046,7 @@ class TextInput { ti.activated?.($, true); ti.enter.btn.down = false; - // ti.activatedOnce = true; + ti.activatedOnce = true; if (ti.text.length > 0) { ti.copy.btn.disabled = true; ti.copy.btn.removeFromDom($, "copy"); @@ -1323,9 +1331,15 @@ class TextInput { this.blink.flip(true); } - if (e.is("prompt:text:replace")) { + // This should only be possible when the text box is locked, unless + // it's the first activation. + if ( + e.is("prompt:text:replace") && + (!this.activatedOnce || this.lock === false) + ) { this.text = e.text; - this.#prompt.snapTo(e.text.slice(0, e.cursor)); + this.#lastUserText = e.text; + this.#prompt.snapTo(this.text.slice(0, e.cursor)); this.runnable = true; this.blink.flip(true); this.selection = null; @@ -1336,7 +1350,7 @@ class TextInput { // this.blink.flip(true); // } - if (e.is("prompt:text:cursor")) { + if (e.is("prompt:text:cursor") && this.lock === false) { if (e.cursor === this.text.length) { this.snap(); } else { diff --git a/system/public/aesthetic.computer/systems/prompt-system.mjs b/system/public/aesthetic.computer/systems/prompt-system.mjs index 7bb2867e40..3c5238a972 100644 --- a/system/public/aesthetic.computer/systems/prompt-system.mjs +++ b/system/public/aesthetic.computer/systems/prompt-system.mjs @@ -45,6 +45,7 @@ export async function prompt_boot( } input.lock = true; + $.send({ type: "keyboard:lock" }); input.enter.btn.disabled = true; // Disable any paste button. @@ -55,7 +56,10 @@ export async function prompt_boot( input.canType = false; const halted = await halt?.($, text); - if (!$.leaving()) input.lock = false; + if (!$.leaving()) { + input.lock = false; + $.send({ type: "keyboard:unlock" }); + } if (halted) { messageComplete = true; @@ -65,6 +69,7 @@ export async function prompt_boot( // (Immediate bot-style reply) if (halted.replied) { input.lock = false; + $.send({ type: "keyboard:unlock" }); input.runnable = false; input.bakePrintedText(); input.showButton($); @@ -75,6 +80,7 @@ export async function prompt_boot( if ($.leaving()) { input.lock = false; + $.send({ type: "keyboard:unlock" }); return; // Keep the screen emptied out if we are leaving. } @@ -103,6 +109,10 @@ export async function prompt_boot( abortMessage = ""; abort?.(); // Prevent fail from running here... input.activate(input); + $.send({ + type: "keyboard:text:replace", + content: { text: abortMessage }, + }); }; abort = conversation.ask( @@ -116,6 +126,7 @@ export async function prompt_boot( function done() { messageComplete = true; processing = input.lock = false; + $.send({ type: "keyboard:unlock" }); reply?.(input.text, input); input.bakePrintedText(); input.clearUserText(); @@ -134,10 +145,12 @@ export async function prompt_boot( }, function fail() { input.text = abortMessage; + input.snap(); $.needsPaint(); reply?.(input.text); input.submittedText = ""; processing = input.lock = false; + $.send({ type: "keyboard:unlock" }); input.bakePrintedText(); input.runnable = false; if (input.text.length > 0) { @@ -148,7 +161,7 @@ export async function prompt_boot( ); }, { - autolock: false, + // autolock: false, wrap, scheme, copied, @@ -181,8 +194,9 @@ export function prompt_act($) { if ( !messageComplete && processing && - (e.is("keyboard:down:escape") || - (e.is("keyboard:down:`") && slug === "prompt")) + e.is("keyboard:down") + //(e.is("keyboard:down:escape") || + // (e.is("keyboard:down:`") && slug === "prompt")) ) { cancel(); }