show tiny browser
This commit is contained in:
parent
a87564b082
commit
6fcffc65f9
|
|
@ -4,23 +4,31 @@
|
||||||
|
|
||||||
import { $, $$ } from "./dom"
|
import { $, $$ } from "./dom"
|
||||||
import { focusInput } from "./focus"
|
import { focusInput } from "./focus"
|
||||||
|
import { scrollback } from "./dom"
|
||||||
|
import { addInput } from "./scrollback"
|
||||||
|
import { randomId } from "../shared/utils"
|
||||||
|
|
||||||
|
const HEIGHT = 540
|
||||||
|
const WIDTH = 960
|
||||||
|
|
||||||
const controls = $("browser-controls") as HTMLDivElement
|
const controls = $("browser-controls") as HTMLDivElement
|
||||||
const address = $("browser-address") as HTMLSpanElement
|
const address = $("browser-address") as HTMLSpanElement
|
||||||
let iframe: HTMLIFrameElement
|
let iframe: HTMLIFrameElement
|
||||||
let iframeWindow: Window
|
let realUrl = ""
|
||||||
|
let showInput = true
|
||||||
|
|
||||||
export function isBrowsing(): boolean {
|
export function isBrowsing(): boolean {
|
||||||
return document.querySelector("iframe.browser.active") !== null
|
return document.querySelector("iframe.browser.active") !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openBrowser(url: string) {
|
export function openBrowser(url: string, openedVia: "click" | "command" = "click") {
|
||||||
|
showInput = openedVia === "click"
|
||||||
|
|
||||||
iframe = $$("iframe.browser.active") as HTMLIFrameElement
|
iframe = $$("iframe.browser.active") as HTMLIFrameElement
|
||||||
iframeWindow = iframe.contentWindow as Window
|
|
||||||
iframe.src = url
|
iframe.src = url
|
||||||
iframe.sandbox.add("allow-scripts", "allow-same-origin", "allow-forms")
|
iframe.sandbox.add("allow-scripts", "allow-same-origin", "allow-forms")
|
||||||
iframe.height = "540"
|
iframe.height = String(HEIGHT)
|
||||||
iframe.width = "960"
|
iframe.width = String(WIDTH)
|
||||||
iframe.tabIndex = 0
|
iframe.tabIndex = 0
|
||||||
|
|
||||||
window.addEventListener("message", handleAppMessage)
|
window.addEventListener("message", handleAppMessage)
|
||||||
|
|
@ -35,6 +43,28 @@ export function openBrowser(url: string) {
|
||||||
setAddress(url)
|
setAddress(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeBrowser() {
|
||||||
|
window.removeEventListener("keydown", handleBrowserKeydown)
|
||||||
|
window.removeEventListener("message", handleAppMessage)
|
||||||
|
controls.removeEventListener("click", handleClick)
|
||||||
|
iframe.removeEventListener("load", handlePageLoad)
|
||||||
|
|
||||||
|
const id = randomId()
|
||||||
|
if (showInput)
|
||||||
|
addInput(id, "browse " + realUrl, "ok")
|
||||||
|
|
||||||
|
iframe.height = String(HEIGHT / 2)
|
||||||
|
iframe.width = String(WIDTH / 2)
|
||||||
|
iframe.style.pointerEvents = "none"
|
||||||
|
iframe.tabIndex = -1
|
||||||
|
iframe.classList.remove("fullscreen", "active")
|
||||||
|
iframe.style.border = "2px solid var(--c64-light-blue)"
|
||||||
|
scrollback.append(iframe)
|
||||||
|
|
||||||
|
controls.style.display = "none"
|
||||||
|
focusInput()
|
||||||
|
}
|
||||||
|
|
||||||
function handleAppMessage(event: MessageEvent) {
|
function handleAppMessage(event: MessageEvent) {
|
||||||
const origin = event.origin
|
const origin = event.origin
|
||||||
if (!origin.includes('localhost') && !origin.match(/\.local$/)) {
|
if (!origin.includes('localhost') && !origin.match(/\.local$/)) {
|
||||||
|
|
@ -74,20 +104,6 @@ function handleAppMessage(event: MessageEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeBrowser() {
|
|
||||||
window.removeEventListener("keydown", handleBrowserKeydown)
|
|
||||||
window.removeEventListener("message", handleAppMessage)
|
|
||||||
controls.removeEventListener("click", handleClick)
|
|
||||||
iframe.removeEventListener("load", handlePageLoad)
|
|
||||||
|
|
||||||
iframe.src = 'about:blank'
|
|
||||||
setTimeout(() => {
|
|
||||||
iframe.remove()
|
|
||||||
controls.style.display = "none"
|
|
||||||
focusInput()
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBrowserKeydown(e: KeyboardEvent) {
|
function handleBrowserKeydown(e: KeyboardEvent) {
|
||||||
if (e.key === "Escape" || (e.ctrlKey && e.key === "c")) {
|
if (e.key === "Escape" || (e.ctrlKey && e.key === "c")) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
@ -123,6 +139,7 @@ function handlePageLoad() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAddress(url: string) {
|
function setAddress(url: string) {
|
||||||
|
realUrl = url
|
||||||
address.textContent = url.replace(/https?:\/\//, "")
|
address.textContent = url.replace(/https?:\/\//, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,17 @@
|
||||||
// temporary hack for browser commands
|
// temporary hack for browser commands
|
||||||
|
|
||||||
import type { CommandOutput } from "../shared/types"
|
import type { CommandOutput } from "../shared/types"
|
||||||
|
import { openBrowser } from "./browser"
|
||||||
import { scrollback, content } from "./dom"
|
import { scrollback, content } from "./dom"
|
||||||
|
import { focusInput } from "./focus"
|
||||||
import { resize } from "./resize"
|
import { resize } from "./resize"
|
||||||
import { autoScroll } from "./scrollback"
|
|
||||||
import { sessionId } from "./session"
|
import { sessionId } from "./session"
|
||||||
import { send } from "./websocket"
|
import { send } from "./websocket"
|
||||||
import { focusInput } from "./focus"
|
|
||||||
|
|
||||||
export const commands: string[] = []
|
export const commands: string[] = []
|
||||||
|
|
||||||
export const browserCommands: Record<string, (...args: string[]) => void | Promise<void> | CommandOutput> = {
|
export const browserCommands: Record<string, (...args: string[]) => void | Promise<void> | CommandOutput> = {
|
||||||
|
browse: (url: string) => openBrowser(url, "command"),
|
||||||
"browser-session": () => sessionId,
|
"browser-session": () => sessionId,
|
||||||
clear: () => scrollback.innerHTML = "",
|
clear: () => scrollback.innerHTML = "",
|
||||||
commands: () => {
|
commands: () => {
|
||||||
|
|
@ -27,7 +28,6 @@ export const browserCommands: Record<string, (...args: string[]) => void | Promi
|
||||||
content.style.display = ""
|
content.style.display = ""
|
||||||
document.body.dataset.mode = mode
|
document.body.dataset.mode = mode
|
||||||
resize()
|
resize()
|
||||||
autoScroll()
|
|
||||||
focusInput()
|
focusInput()
|
||||||
},
|
},
|
||||||
reload: () => window.location.reload(),
|
reload: () => window.location.reload(),
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,26 @@ import { scrollback, cmdInput, $$ } from "./dom"
|
||||||
import { randomId } from "../shared/utils"
|
import { randomId } from "../shared/utils"
|
||||||
|
|
||||||
type InputStatus = "waiting" | "streaming" | "ok" | "error"
|
type InputStatus = "waiting" | "streaming" | "ok" | "error"
|
||||||
|
const statusColors = {
|
||||||
|
waiting: "yellow",
|
||||||
|
streaming: "purple",
|
||||||
|
ok: "green",
|
||||||
|
error: "red"
|
||||||
|
}
|
||||||
|
|
||||||
export function initScrollback() {
|
export function initScrollback() {
|
||||||
window.addEventListener("click", handleInputClick)
|
window.addEventListener("click", handleInputClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function autoScroll() {
|
|
||||||
// requestAnimationFrame(() => scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight)
|
|
||||||
// scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
export function insert(node: HTMLElement) {
|
export function insert(node: HTMLElement) {
|
||||||
scrollback.append(node)
|
scrollback.append(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addInput(id: string, input: string) {
|
export function addInput(id: string, input: string, status?: InputStatus) {
|
||||||
const parent = $$("li.input")
|
const parent = $$("li.input")
|
||||||
const status = $$("span.status.yellow", "•")
|
const statusSpan = $$(`span.status.${statusColors[status || "waiting"]}`, "•")
|
||||||
const content = $$("span.content", input)
|
const content = $$("span.content", input)
|
||||||
parent.append(status, content)
|
parent.append(statusSpan, content)
|
||||||
parent.dataset.id = id
|
parent.dataset.id = id
|
||||||
|
|
||||||
insert(parent)
|
insert(parent)
|
||||||
|
|
@ -36,15 +37,8 @@ export function setStatus(id: string, status: InputStatus) {
|
||||||
const statusEl = document.querySelector(`[data-id="${id}"].input .status`)
|
const statusEl = document.querySelector(`[data-id="${id}"].input .status`)
|
||||||
if (!statusEl) return
|
if (!statusEl) return
|
||||||
|
|
||||||
const colors = {
|
statusEl.classList.remove(...Object.values(statusColors))
|
||||||
waiting: "yellow",
|
statusEl.classList.add(statusColors[status])
|
||||||
streaming: "purple",
|
|
||||||
ok: "green",
|
|
||||||
error: "red"
|
|
||||||
}
|
|
||||||
|
|
||||||
statusEl.classList.remove(...Object.values(colors))
|
|
||||||
statusEl.classList.add(colors[status])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addOutput(id: string, output: CommandOutput) {
|
export function addOutput(id: string, output: CommandOutput) {
|
||||||
|
|
@ -65,8 +59,6 @@ export function addOutput(id: string, output: CommandOutput) {
|
||||||
} else {
|
} else {
|
||||||
insert(item)
|
insert(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
autoScroll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addErrorMessage(message: string) {
|
export function addErrorMessage(message: string) {
|
||||||
|
|
@ -87,8 +79,6 @@ export function appendOutput(id: string, output: CommandOutput) {
|
||||||
item.innerHTML += content
|
item.innerHTML += content
|
||||||
else
|
else
|
||||||
item.textContent += content
|
item.textContent += content
|
||||||
|
|
||||||
autoScroll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function replaceOutput(id: string, output: CommandOutput) {
|
export function replaceOutput(id: string, output: CommandOutput) {
|
||||||
|
|
@ -105,8 +95,6 @@ export function replaceOutput(id: string, output: CommandOutput) {
|
||||||
item.innerHTML = content
|
item.innerHTML = content
|
||||||
else
|
else
|
||||||
item.textContent = content
|
item.textContent = content
|
||||||
|
|
||||||
autoScroll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function processOutput(output: CommandOutput): ["html" | "text", string] {
|
function processOutput(output: CommandOutput): ["html" | "text", string] {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user