Compare commits
No commits in common. "f828384dbadb764f723b9d56fc698a50f5719176" and "15a8ff29e62f75e7953b36fa45fcfd6b7bfaf241" have entirely different histories.
f828384dba
...
15a8ff29e6
|
|
@ -52,10 +52,10 @@ https://wakamaifondue.com/
|
||||||
|
|
||||||
## Pluto Goals: Phase 2
|
## Pluto Goals: Phase 2
|
||||||
|
|
||||||
- [x] public tunnel for your NOSE webapps
|
- [ ] public tunnel for your NOSE webapps
|
||||||
- [x] public tunnel lives through reboots
|
- [ ] public tunnel lives through reboots
|
||||||
- [x] self updating NOSE server
|
- [ ] self updating NOSE server
|
||||||
- [x] `pub/` static hosting in webapps
|
- [ ] `pub/` static hosting in webapps
|
||||||
- [ ] game/bin/www cartridges
|
- [ ] game/bin/www cartridges
|
||||||
- [ ] upload files to projects
|
- [ ] upload files to projects
|
||||||
- [ ] pico8-style games
|
- [ ] pico8-style games
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
export const game = true
|
export const game = true
|
||||||
|
|
||||||
import type { GameContext, InputState } from "@/shared/game"
|
import type { GameContext, InputState } from "@/shared/game"
|
||||||
import { rng } from "@/shared/utils"
|
import { rng } from "@/shared/utils.ts"
|
||||||
|
|
||||||
const WIDTH = 960
|
const WIDTH = 960
|
||||||
const HEIGHT = 540
|
const HEIGHT = 540
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// List all the games installed on the system.
|
|
||||||
|
|
||||||
import { readdirSync } from "fs"
|
|
||||||
import { join } from "path"
|
|
||||||
import { NOSE_SYS_BIN } from "@/config"
|
|
||||||
|
|
||||||
export default async function () {
|
|
||||||
let games = await Promise.all(readdirSync(NOSE_SYS_BIN, { withFileTypes: true }).map(async file => {
|
|
||||||
if (!file.isFile()) return
|
|
||||||
|
|
||||||
const code = await Bun.file(join(NOSE_SYS_BIN, file.name)).text()
|
|
||||||
|
|
||||||
if (/^export const game\s*=\s*true\s*;?\s*$/m.test(code))
|
|
||||||
return file.name.replace(".tsx", "").replace(".ts", "")
|
|
||||||
})).then(games => games.filter(file => file))
|
|
||||||
|
|
||||||
return <>
|
|
||||||
{games.map(game => <a href={`#${game}`}>{game}</a>)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
export const game = true
|
export const game = true
|
||||||
|
|
||||||
import type { GameContext, InputState } from "@/shared/game"
|
import type { GameContext, InputState } from "@/shared/game"
|
||||||
import { rng } from "@/shared/utils"
|
import { rng } from "@/shared/utils.ts"
|
||||||
|
|
||||||
const CELL = 20
|
const CELL = 20
|
||||||
const WIDTH = 30
|
const WIDTH = 30
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
export const game = true
|
export const game = true
|
||||||
|
|
||||||
import type { GameContext, InputState } from "@/shared/game"
|
import type { GameContext, InputState } from "@/shared/game"
|
||||||
import { randomElement, randomIndex } from "@/shared/utils"
|
import { randomElement, randomIndex } from "@/shared/utils.ts"
|
||||||
|
|
||||||
const COLS = 10
|
const COLS = 10
|
||||||
const ROWS = 20
|
const ROWS = 20
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import { initHistory } from "./history.js"
|
||||||
import { initHyperlink } from "./hyperlink.js"
|
import { initHyperlink } from "./hyperlink.js"
|
||||||
import { initInput } from "./input.js"
|
import { initInput } from "./input.js"
|
||||||
import { initResize } from "./resize.js"
|
import { initResize } from "./resize.js"
|
||||||
import { initScrollback } from "./scrollback.js"
|
|
||||||
import { startVramCounter } from "./vram.js"
|
import { startVramCounter } from "./vram.js"
|
||||||
import { startConnection } from "./websocket.js"
|
import { startConnection } from "./websocket.js"
|
||||||
|
|
||||||
|
|
@ -20,7 +19,6 @@ initHistory()
|
||||||
initHyperlink()
|
initHyperlink()
|
||||||
initInput()
|
initInput()
|
||||||
initResize()
|
initResize()
|
||||||
initScrollback()
|
|
||||||
|
|
||||||
startConnection()
|
startConnection()
|
||||||
startVramCounter()
|
startVramCounter()
|
||||||
|
|
@ -2,16 +2,12 @@
|
||||||
// The scrollback shows your history of interacting with the shell.
|
// The scrollback shows your history of interacting with the shell.
|
||||||
// input, output, etc
|
// input, output, etc
|
||||||
|
|
||||||
import type { CommandOutput } from "../shared/types.js"
|
import { scrollback, $$ } from "./dom.js"
|
||||||
import { scrollback, cmdInput, $$ } from "./dom.js"
|
|
||||||
import { randomId } from "../shared/utils.js"
|
import { randomId } from "../shared/utils.js"
|
||||||
|
import type { CommandOutput } from "../shared/types.js"
|
||||||
|
|
||||||
type InputStatus = "waiting" | "streaming" | "ok" | "error"
|
type InputStatus = "waiting" | "streaming" | "ok" | "error"
|
||||||
|
|
||||||
export function initScrollback() {
|
|
||||||
window.addEventListener("click", handleInputClick)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function autoScroll() {
|
export function autoScroll() {
|
||||||
// requestAnimationFrame(() => scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight)
|
// requestAnimationFrame(() => scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight)
|
||||||
// scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight
|
// scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight
|
||||||
|
|
@ -67,11 +63,10 @@ export function addOutput(id: string, output: CommandOutput) {
|
||||||
item.textContent = content
|
item.textContent = content
|
||||||
|
|
||||||
const input = document.querySelector(`[data-id="${id}"].input`)
|
const input = document.querySelector(`[data-id="${id}"].input`)
|
||||||
if (input instanceof HTMLLIElement) {
|
if (input instanceof HTMLLIElement)
|
||||||
input.parentNode!.insertBefore(item, input.nextSibling)
|
input.parentNode!.insertBefore(item, input.nextSibling)
|
||||||
} else {
|
else
|
||||||
insert(item)
|
insert(item)
|
||||||
}
|
|
||||||
|
|
||||||
autoScroll()
|
autoScroll()
|
||||||
}
|
}
|
||||||
|
|
@ -140,13 +135,3 @@ function processOutput(output: CommandOutput): ["html" | "text", string] {
|
||||||
|
|
||||||
return [html ? "html" : "text", content]
|
return [html ? "html" : "text", content]
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleInputClick(e: MouseEvent) {
|
|
||||||
const target = e.target
|
|
||||||
|
|
||||||
if (!(target instanceof HTMLElement)) return
|
|
||||||
|
|
||||||
if (target.matches(".input .content")) {
|
|
||||||
cmdInput.value = target.textContent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ import { addErrorMessage } from "./scrollback.js"
|
||||||
|
|
||||||
const MAX_RETRIES = 5
|
const MAX_RETRIES = 5
|
||||||
let retries = 0
|
let retries = 0
|
||||||
let connected = false
|
|
||||||
let msgQueue: Message[] = []
|
|
||||||
|
|
||||||
let ws: WebSocket | null = null
|
let ws: WebSocket | null = null
|
||||||
|
|
||||||
|
|
@ -22,21 +20,10 @@ export function startConnection() {
|
||||||
ws.onmessage = receive
|
ws.onmessage = receive
|
||||||
ws.onclose = retryConnection
|
ws.onclose = retryConnection
|
||||||
ws.onerror = () => ws?.close()
|
ws.onerror = () => ws?.close()
|
||||||
ws.onopen = () => {
|
|
||||||
connected = true
|
|
||||||
msgQueue.forEach(msg => send(msg))
|
|
||||||
msgQueue.length = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send any message
|
// send any message
|
||||||
export function send(msg: Message) {
|
export function send(msg: Message) {
|
||||||
if (!connected) {
|
|
||||||
msgQueue.push(msg)
|
|
||||||
startConnection()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!msg.session) msg.session = sessionID
|
if (!msg.session) msg.session = sessionID
|
||||||
ws?.readyState === 1 && ws.send(JSON.stringify(msg))
|
ws?.readyState === 1 && ws.send(JSON.stringify(msg))
|
||||||
console.log("-> send", msg)
|
console.log("-> send", msg)
|
||||||
|
|
@ -54,8 +41,6 @@ export function close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function retryConnection() {
|
function retryConnection() {
|
||||||
connected = false
|
|
||||||
|
|
||||||
if (retries >= MAX_RETRIES) {
|
if (retries >= MAX_RETRIES) {
|
||||||
addErrorMessage(`!! Failed to reconnect ${retries} times. Server is down.`)
|
addErrorMessage(`!! Failed to reconnect ${retries} times. Server is down.`)
|
||||||
if (ws) ws.onclose = () => { }
|
if (ws) ws.onclose = () => { }
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ app.use("*", async (c, next) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => {
|
app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => {
|
||||||
let path = "./src/" + c.req.path.replace("..", ".")
|
const path = "./src/" + c.req.path.replace("..", ".")
|
||||||
|
|
||||||
// path must end in .js or .ts
|
// path must end in .js or .ts
|
||||||
if (!path.endsWith(".js") && !path.endsWith(".ts")) path += ".ts"
|
if (!path.endsWith(".js") && !path.endsWith(".ts")) return c.text("File not found", 404)
|
||||||
|
|
||||||
const ts = path.replace(".js", ".ts")
|
const ts = path.replace(".js", ".ts")
|
||||||
if (isFile(ts)) {
|
if (isFile(ts)) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user