Complete redo of content indexing and querying (#517)

Complete redo of data store
Introduces live queries and live templates
This commit is contained in:
Zef Hemel
2023-10-03 14:16:33 +02:00
committed by GitHub
parent 7af98e7c7b
commit 0313565610
200 changed files with 4675 additions and 4363 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
import { FilterList } from "./filter.tsx";
import { FilterOption, PageMeta } from "../types.ts";
import { FilterOption } from "../types.ts";
import { CompletionContext, CompletionResult } from "../deps.ts";
import { PageMeta } from "$sb/types.ts";
export function PageNavigator({
allPages,
@@ -51,7 +52,7 @@ export function PageNavigator({
darkMode={darkMode}
completer={completer}
allowNew={true}
helpText="Start typing the page name to filter results, press <code>Return</code> to open."
helpText="Press <code>Enter</code> to open the selected page, or <code>Shift-Enter</code> to create a new page."
newHint="Create page"
completePrefix={completePrefix}
onSelect={(opt) => {
+1 -91
View File
@@ -1,97 +1,7 @@
import { useEffect, useRef } from "../deps.ts";
import { Client } from "../client.ts";
import { PanelConfig } from "../types.ts";
export const panelHtml = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<base target="_top">
<script>
const pendingRequests = new Map();
let syscallReqId = 0;
self.syscall = async (name, ...args) => {
return await new Promise((resolve, reject) => {
syscallReqId++;
pendingRequests.set(syscallReqId, { resolve, reject });
window.parent.postMessage({
type: "syscall",
id: syscallReqId,
name,
args,
}, "*");
});
};
window.addEventListener("message", (message) => {
const data = message.data;
switch (data.type) {
case "html":
document.body.innerHTML = data.html;
if (data.script) {
try {
eval(data.script);
} catch (e) {
console.error("Error evaling script", e);
}
}
break;
case "syscall-response":
{
const syscallId = data.id;
const lookup = pendingRequests.get(syscallId);
if (!lookup) {
console.log(
"Current outstanding requests",
pendingRequests,
"looking up",
syscallId,
);
throw Error("Invalid request id");
}
pendingRequests.delete(syscallId);
if (data.error) {
lookup.reject(new Error(data.error));
} else {
lookup.resolve(data.result);
}
}
break;
}
});
// DEPRECATED: Use syscall("event.dispatch", ...) instead
function sendEvent(name, ...args) {
window.parent.postMessage({ type: "event", name, args, }, "*");
}
function api(obj) {
window.parent.postMessage(obj, "*");
}
function updateHeight() {
api({
type: "setHeight",
height: document.documentElement.offsetHeight,
});
}
function loadJsByUrl(url) {
const script = document.createElement("script");
script.src = url;
return new Promise((resolve) => {
script.onload = resolve;
document.documentElement.firstChild.appendChild(script);
});
}
</script>
</head>
<body>
Loading...
</body>
</html>`;
import { panelHtml } from "./panel_html.ts";
export function Panel({
config,
+103
View File
@@ -0,0 +1,103 @@
export const panelHtml = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<base target="_top">
<script>
const pendingRequests = new Map();
let syscallReqId = 0;
self.syscall = async (name, ...args) => {
return await new Promise((resolve, reject) => {
syscallReqId++;
pendingRequests.set(syscallReqId, { resolve, reject });
window.parent.postMessage({
type: "syscall",
id: syscallReqId,
name,
args,
}, "*");
});
};
window.addEventListener("message", (message) => {
const data = message.data;
switch (data.type) {
case "html":
document.body.innerHTML = data.html;
if(data.theme) {
document.getElementsByTagName("html")[0].setAttribute("data-theme", data.theme);
}
if (data.script) {
try {
eval(data.script);
} catch (e) {
console.error("Error evaling script", e);
}
}
break;
case "syscall-response":
{
const syscallId = data.id;
const lookup = pendingRequests.get(syscallId);
if (!lookup) {
console.log(
"Current outstanding requests",
pendingRequests,
"looking up",
syscallId,
);
throw Error("Invalid request id");
}
pendingRequests.delete(syscallId);
if (data.error) {
lookup.reject(new Error(data.error));
} else {
lookup.resolve(data.result);
}
}
break;
}
});
function api(obj) {
window.parent.postMessage(obj, "*");
}
let oldHeight = undefined;
let heightChecks = 0;
function updateHeight() {
const body = document.body, html = document.documentElement;
let height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
heightChecks++;
if(height !== oldHeight) {
oldHeight = height;
api({
type: "setHeight",
height: height,
});
}
if(heightChecks < 25) {
setTimeout(updateHeight, 100);
}
}
setTimeout(() => {
updateHeight();
});
function loadJsByUrl(url) {
const script = document.createElement("script");
script.src = url;
return new Promise((resolve) => {
script.onload = resolve;
document.documentElement.firstChild.appendChild(script);
});
}
</script>
</head>
<body>
</body>
</html>`;
+96
View File
@@ -0,0 +1,96 @@
import { WidgetContent } from "$sb/app_event.ts";
import { Client } from "../client.ts";
import { panelHtml } from "./panel_html.ts";
export function createWidgetSandboxIFrame(
client: Client,
widgetHeightCacheKey: string | null,
content: WidgetContent | Promise<WidgetContent>,
onMessage?: (message: any) => void,
) {
const iframe = document.createElement("iframe");
iframe.srcdoc = panelHtml;
// iframe.style.height = "150px";
const messageListener = (evt: any) => {
(async () => {
if (evt.source !== iframe.contentWindow) {
return;
}
const data = evt.data;
if (!data) {
return;
}
switch (data.type) {
case "syscall": {
const { id, name, args } = data;
try {
const result = await client.system.localSyscall(name, args);
if (!iframe.contentWindow) {
// iFrame already went away
return;
}
iframe.contentWindow!.postMessage({
type: "syscall-response",
id,
result,
});
} catch (e: any) {
if (!iframe.contentWindow) {
// iFrame already went away
return;
}
iframe.contentWindow!.postMessage({
type: "syscall-response",
id,
error: e.message,
});
}
break;
}
case "setHeight":
iframe.style.height = data.height + "px";
if (widgetHeightCacheKey) {
client.space.setCachedWidgetHeight(
widgetHeightCacheKey,
data.height,
);
}
break;
default:
if (onMessage) {
onMessage(data);
}
}
})().catch((e) => {
console.error("Message listener error", e);
});
};
iframe.onload = () => {
// Subscribe to message event on global object (to receive messages from iframe)
globalThis.addEventListener("message", messageListener);
// Only run this code once
iframe.onload = null;
Promise.resolve(content).then((content) => {
if (content.html) {
iframe.contentWindow!.postMessage({
type: "html",
html: content.html,
script: content.script,
theme: document.getElementsByTagName("html")[0].dataset.theme,
});
} else if (content.url) {
iframe.contentWindow!.location.href = content.url;
if (content.height) {
iframe.style.height = content.height + "px";
}
if (content.width) {
iframe.style.width = content.width + "px";
}
}
}).catch(console.error);
};
return iframe;
}