add: littleweb full
This commit is contained in:
parent
3fc0872867
commit
d67e7c9c33
32 changed files with 1699 additions and 71 deletions
211
crates/app/src/public/html/littleweb/browser.lisp
Normal file
211
crates/app/src/public/html/littleweb/browser.lisp
Normal file
|
@ -0,0 +1,211 @@
|
|||
(text "{% extends \"root.html\" %} {% block head %}")
|
||||
(title
|
||||
(text "{{ config.name }}"))
|
||||
|
||||
(text "{% endblock %} {% block body %}")
|
||||
(div
|
||||
("id" "panel")
|
||||
("class" "flex flex-row gap-2")
|
||||
(a
|
||||
("class" "button camo")
|
||||
("href" "/")
|
||||
(icon (text "house")))
|
||||
|
||||
(button
|
||||
("class" "lowered")
|
||||
("onclick" "back()")
|
||||
(icon (text "arrow-left")))
|
||||
|
||||
(button
|
||||
("class" "lowered")
|
||||
("onclick" "forward()")
|
||||
(icon (text "arrow-right")))
|
||||
|
||||
(button
|
||||
("class" "lowered")
|
||||
("onclick" "reload()")
|
||||
(icon (text "rotate-cw")))
|
||||
|
||||
(form
|
||||
("class" "w-full flex gap-1 flex-row")
|
||||
("onsubmit" "event.preventDefault(); littleweb_navigate(event.target.uri.getAttribute('true_value'))")
|
||||
(input
|
||||
("type" "uri")
|
||||
("class" "w-full")
|
||||
("true_value" "{{ path }}")
|
||||
("name" "uri")
|
||||
("id" "uri"))
|
||||
|
||||
(button ("class" "lowered small square") (icon (text "arrow-right"))))
|
||||
|
||||
(text "{% if user -%}")
|
||||
(div
|
||||
("class" "dropdown")
|
||||
(button
|
||||
("class" "flex-row camo")
|
||||
("onclick" "trigger('atto::hooks::dropdown', [event])")
|
||||
("exclude" "dropdown")
|
||||
("style" "gap: var(--pad-1) !important")
|
||||
(text "{{ components::avatar(username=user.username, size=\"24px\") }}")
|
||||
(icon_class (text "chevron-down") (text "dropdown-arrow")))
|
||||
|
||||
(text "{{ components::user_menu() }}"))
|
||||
(text "{%- endif %}"))
|
||||
|
||||
(iframe
|
||||
("id" "browser_iframe")
|
||||
("frameborder" "0")
|
||||
("src" "{% if path -%} {{ config.lw_host }}/api/v1/net/{{ path }} {%- endif %}"))
|
||||
|
||||
(style
|
||||
("data-turbo-temporary" "true")
|
||||
(text ":root {
|
||||
--panel-height: 45px;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#panel {
|
||||
width: 100dvw;
|
||||
height: var(--panel-height);
|
||||
padding: var(--pad-2);
|
||||
}
|
||||
|
||||
#panel input {
|
||||
border: none;
|
||||
background: var(--color-lowered);
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
#panel input:focus {
|
||||
background: var(--color-super-lowered);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
#panel input:focus {
|
||||
position: fixed;
|
||||
width: calc(100dvw - (62px + var(--pad-2) * 2)) !important;
|
||||
left: var(--pad-2);
|
||||
}
|
||||
}
|
||||
|
||||
#panel button:not(.inner *),
|
||||
#panel a.button:not(.inner *),
|
||||
#panel input {
|
||||
--h: 28.2px;
|
||||
height: var(--h);
|
||||
min-height: var(--h);
|
||||
max-height: var(--h);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#panel button:not(.inner *),
|
||||
#panel a.button:not(.inner *) {
|
||||
padding: var(--pad-1) var(--pad-2);
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100dvw;
|
||||
height: calc(100dvh - var(--panel-height));
|
||||
}"))
|
||||
|
||||
(script
|
||||
(text "function littleweb_navigate(uri) {
|
||||
if (!uri.includes(\".html\")) {
|
||||
uri = `${uri}/index.html`;
|
||||
}
|
||||
|
||||
if (!uri.startsWith(\"atto://\")) {
|
||||
uri = `atto://${uri}`;
|
||||
}
|
||||
|
||||
// ...
|
||||
console.log(\"navigate\", uri);
|
||||
document.getElementById(\"browser_iframe\").src = `{{ config.lw_host|safe }}/api/v1/net/${uri}`;
|
||||
}
|
||||
|
||||
document.getElementById(\"browser_iframe\").addEventListener(\"load\", (e) => {
|
||||
console.log(\"web content loaded\");
|
||||
});
|
||||
|
||||
window.addEventListener(\"message\", (e) => {
|
||||
if (typeof e.data !== \"string\") {
|
||||
console.log(\"refuse message (bad type)\");
|
||||
return;
|
||||
}
|
||||
|
||||
const data = JSON.parse(e.data);
|
||||
|
||||
if (!data.t) {
|
||||
console.log(\"refuse message (not for tetratto)\");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(\"received message\");
|
||||
|
||||
if (data.event === \"change_url\") {
|
||||
const uri = new URL(data.target).pathname.slice(\"/api/v1/net/\".length);
|
||||
window.history.pushState(null, null, `/net/${uri.replace(\"atto://\", \"\")}`);
|
||||
document.getElementById(\"uri\").setAttribute(\"true_value\", uri);
|
||||
}
|
||||
});
|
||||
|
||||
function back() {
|
||||
post_message({ t: true, event: \"back\" });
|
||||
}
|
||||
|
||||
function forward() {
|
||||
post_message({ t: true, event: \"forward\" });
|
||||
}
|
||||
|
||||
function reload() {
|
||||
post_message({ t: true, event: \"reload\" });
|
||||
}
|
||||
|
||||
function post_message(data) {
|
||||
const origin = new URL(document.getElementById(\"browser_iframe\").src).origin;
|
||||
document.getElementById(\"browser_iframe\").contentWindow.postMessage(JSON.stringify(data), origin);
|
||||
}
|
||||
|
||||
// handle dropdowns
|
||||
window.addEventListener(\"blur\", () => {
|
||||
trigger(\"atto::hooks::dropdown.close\");
|
||||
});
|
||||
|
||||
// url bar focus
|
||||
document.getElementById(\"uri\").addEventListener(\"input\", (e) => {
|
||||
e.target.setAttribute(\"true_value\", e.target.value);
|
||||
});
|
||||
|
||||
let is_focused = false;
|
||||
|
||||
document.getElementById(\"uri\").addEventListener(\"mouseenter\", (e) => {
|
||||
e.target.value = e.target.getAttribute(\"true_value\").replace(\"/index.html\", \"\");
|
||||
});
|
||||
|
||||
document.getElementById(\"uri\").addEventListener(\"mouseleave\", (e) => {
|
||||
if (is_focused) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.target.value = e.target.getAttribute(\"true_value\").replace(\"atto://\", \"\").split(\"/\")[0];
|
||||
});
|
||||
|
||||
document.getElementById(\"uri\").addEventListener(\"focus\", (e) => {
|
||||
e.target.value = e.target.getAttribute(\"true_value\").replace(\"/index.html\", \"\");
|
||||
is_focused = true;
|
||||
});
|
||||
|
||||
document.getElementById(\"uri\").addEventListener(\"blur\", (e) => {
|
||||
e.target.value = e.target.getAttribute(\"true_value\").replace(\"atto://\", \"\").split(\"/\")[0];
|
||||
is_focused = false;
|
||||
});
|
||||
|
||||
document.getElementById(\"uri\").value = document.getElementById(\"uri\").getAttribute(\"true_value\").replace(\"atto://\", \"\").split(\"/\")[0]"))
|
||||
|
||||
(text "{% endblock %}")
|
Loading…
Add table
Add a link
Reference in a new issue