This commit is contained in:
Chris Wanstrath 2025-09-30 23:17:45 -07:00
parent 0ba73b6dac
commit b411ce7013
5 changed files with 51 additions and 40 deletions

View File

@ -140,11 +140,9 @@ input[type="file"]::file-selector-button {
cursor: pointer; cursor: pointer;
} }
input[type="file"] { input[type="file"],
color: var(--c64-dark-blue); input[type="submit"],
} button {
input[type="submit"] {
color: var(--c64-dark-blue); color: var(--c64-dark-blue);
padding: 5px; padding: 5px;
} }

25
src/js/drop.ts Normal file
View File

@ -0,0 +1,25 @@
export function initDrop() {
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
})
document.body.addEventListener("drop", handleDrop)
}
function preventDefaults(e: Event) {
e.preventDefault()
e.stopPropagation()
}
function handleDrop(e: DragEvent) {
const fileInput = document.querySelector("input[type=file]") as HTMLInputElement
const files = e.dataTransfer?.files ?? []
if (files.length > 0) {
const dt = new DataTransfer()
Array.from(files).forEach(f => dt.items.add(f))
fileInput.files = dt.files
fileInput.dispatchEvent(new Event('change', { bubbles: true }))
}
}

View File

@ -1,5 +1,6 @@
import { initCompletion } from "./completion.js" import { initCompletion } from "./completion.js"
import { initCursor } from "./cursor.js" import { initCursor } from "./cursor.js"
import { initDrop } from "./drop.js"
import { initEditor } from "./editor.js" import { initEditor } from "./editor.js"
import { initFocus } from "./focus.js" import { initFocus } from "./focus.js"
import { initForm } from "./form.js" import { initForm } from "./form.js"
@ -14,6 +15,7 @@ import { startConnection } from "./websocket.js"
initCompletion() initCompletion()
initCursor() initCursor()
initDrop()
initFocus() initFocus()
initForm() initForm()
initEditor() initEditor()

View File

@ -100,7 +100,7 @@ app.on(["GET", "POST"], ["/cmd/:name"], async c => {
if (!mod || !mod[method]) if (!mod || !mod[method])
return c.json({ status: "error", output: `No ${method} export in ${cmd}` }, 500) return c.json({ status: "error", output: `No ${method} export in ${cmd}` }, 500)
return c.json(await runCommandFn(sessionId, async () => mod[method](c))) return c.json(await runCommandFn({ sessionId }, async () => mod[method](c)))
} catch (e: any) { } catch (e: any) {
return c.json({ status: "error", output: e.message || e.toString() }, 500) return c.json({ status: "error", output: e.message || e.toString() }, 500)
} }

View File

@ -15,66 +15,52 @@ export async function runCommand(sessionId: string, taskId: string, input: strin
if (!commandExists(cmd)) if (!commandExists(cmd))
return { status: "error", output: `${cmd} not found` } return { status: "error", output: `${cmd} not found` }
let status: "ok" | "error" = "ok" return runCommandFn({ sessionId, taskId, ws }, async () => exec(cmd, args))
let output: CommandOutput = ""
}
export async function runCommandFn(
{ sessionId, taskId, ws }: { sessionId: string, taskId?: string, ws?: any },
fn: () => Promise<CommandResult>
): Promise<CommandResult> {
try {
const state = getState(sessionId, taskId, ws) const state = getState(sessionId, taskId, ws)
return processExecOutput(await ALS.run(state, async () => fn()))
try {
[status, output] = await ALS.run(state, async () => await exec(cmd, args))
} catch (err) { } catch (err) {
status = "error" return { status: "error", output: errorMessage(err) }
output = errorMessage(err) }
} }
return { status, output } async function exec(cmd: string, args: string[]): Promise<CommandResult> {
}
export async function runCommandFn(sessionId: string, fn: () => Promise<CommandResult>) {
let status: "ok" | "error" = "ok"
let output: CommandOutput = ""
const state = getState(sessionId)
try {
const execOutput = await ALS.run(state, async () => await fn())
;[status, output] = processExecOutput(execOutput)
} catch (err) {
status = "error"
output = errorMessage(err)
}
return { status, output }
}
async function exec(cmd: string, args: string[]): Promise<["ok" | "error", CommandOutput]> {
const module = await loadCommandModule(cmd) const module = await loadCommandModule(cmd)
if (module?.game) if (module?.game)
return ["ok", { game: cmd }] return { status: "ok", output: { game: cmd } }
if (!module || !module.default) if (!module || !module.default)
return ["error", `${cmd} has no default export`] return { status: "error", output: `${cmd} has no default export` }
return processExecOutput(await module.default(...args)) return await module.default(...args)
} }
export function processExecOutput(output: string | any): ["ok" | "error", CommandOutput] { export function processExecOutput(output: string | any): CommandResult {
if (typeof output === "string") { if (typeof output === "string") {
return ["ok", output] return { status: "ok", output }
} else if (typeof output === "object") { } else if (typeof output === "object") {
if (output.error) { if (output.error) {
return ["error", output.error] return { status: "error", output: output.error }
} else if (isJSX(output)) { } else if (isJSX(output)) {
return ["ok", { html: output.toString() }] return { status: "ok", output: { html: output.toString() } }
} else if (output.html && isJSX(output.html)) { } else if (output.html && isJSX(output.html)) {
output.html = output.html.toString() output.html = output.html.toString()
return ["ok", output] return { status: "ok", output }
} else { } else {
return ["ok", output] return { status: "ok", output }
} }
} else if (output === undefined) { } else if (output === undefined) {
return ["ok", ""] return { status: "ok", output: "" }
} else { } else {
return ["ok", String(output)] return { status: "ok", output: String(output) }
} }
} }