website: snapshot

This commit is contained in:
nym21
2026-01-22 16:21:09 +01:00
parent b557477770
commit a62a377081
49 changed files with 2101 additions and 8286 deletions

View File

@@ -1,11 +1,13 @@
import { webSockets } from "./utils/ws.js";
import * as formatters from "./utils/format.js";
import { onFirstIntersection, getElementById, isHidden } from "./utils/dom.js";
import signals from "./signals.js";
import { BrkClient } from "./modules/brk-client/index.js";
import { initOptions } from "./options/full.js";
import ufuzzy from "./modules/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.mjs";
import { init as initChart } from "./panes/chart.js";
import {
init as initChart,
setOption as setChartOption,
} from "./panes/chart.js";
import { initSearch } from "./panes/search.js";
import { next } from "./utils/timing.js";
import { replaceHistory } from "./utils/url.js";
import { removeStored, writeToStorage } from "./utils/storage.js";
@@ -19,8 +21,6 @@ import {
navElement,
navLabelElement,
searchElement,
searchInput,
searchResultsElement,
style,
} from "./utils/elements.js";
@@ -106,427 +106,223 @@ function initFrameSelectors() {
}
initFrameSelectors();
signals.createRoot(() => {
const brk = new BrkClient("https://next.bitview.space");
// const brk = new BrkClient("/");
const owner = signals.getOwner();
const brk = new BrkClient("https://next.bitview.space");
// const brk = new BrkClient("/");
console.log(`VERSION = ${brk.VERSION}`);
console.log(`VERSION = ${brk.VERSION}`);
webSockets.kraken1dCandle.onLatest((latest) => {
console.log("close:", latest.close);
window.document.title = `${latest.close.toLocaleString("en-us")} | ${window.location.host}`;
});
webSockets.kraken1dCandle.onLatest((latest) => {
console.log("close:", latest.close);
window.document.title = `${latest.close.toLocaleString("en-us")} | ${window.location.host}`;
});
// function createLastHeightResource() {
// const lastHeight = signals.createSignal(0);
// function fetchLastHeight() {
// utils.api.fetchLast(
// (h) => {
// lastHeight.set(h);
// },
// /** @satisfies {Height} */ (5),
// "height",
// );
// }
// fetchLastHeight();
// setInterval(fetchLastHeight, 10_000);
// return lastHeight;
// }
// const lastHeight = createLastHeightResource();
const options = initOptions(brk);
const options = initOptions({
signals,
brk,
});
window.addEventListener("popstate", (_event) => {
const path = window.document.location.pathname.split("/").filter((v) => v);
let folder = options.tree;
window.addEventListener("popstate", (_event) => {
const path = window.document.location.pathname.split("/").filter((v) => v);
let folder = options.tree;
while (path.length) {
const id = path.shift();
const res = folder.find((v) => id === formatters.stringToId(v.name));
if (!res) throw "Option not found";
if (path.length >= 1) {
if (!("tree" in res)) {
throw "Unreachable";
}
folder = res.tree;
} else {
if ("tree" in res) {
throw "Unreachable";
}
options.selected.set(res);
while (path.length) {
const id = path.shift();
const res = folder.find((v) => id === formatters.stringToId(v.name));
if (!res) throw "Option not found";
if (path.length >= 1) {
if (!("tree" in res)) {
throw "Unreachable";
}
folder = res.tree;
} else {
if ("tree" in res) {
throw "Unreachable";
}
options.selected.set(res);
}
});
function initSelected() {
let firstRun = true;
function initSelectedFrame() {
if (!firstRun) throw Error("Unreachable");
firstRun = false;
const owner = signals.getOwner();
const chartOption = signals.createSignal(
/** @type {ChartOption | null} */ (null),
);
let previousElement = /** @type {HTMLElement | undefined} */ (undefined);
let firstTimeLoadingChart = true;
signals.createScopedEffect(options.selected, (option) => {
/** @type {HTMLElement | undefined} */
let element;
switch (option.kind) {
case "chart": {
element = chartElement;
chartOption.set(option);
if (firstTimeLoadingChart) {
signals.runWithOwner(owner, () =>
initChart({
option: /** @type {Accessor<ChartOption>} */ (chartOption),
brk,
}),
);
}
firstTimeLoadingChart = false;
break;
}
case "link": {
return;
}
}
if (!element) throw "Element should be set";
if (element !== previousElement) {
if (previousElement) previousElement.hidden = true;
element.hidden = false;
}
if (!previousElement) {
replaceHistory({ pathname: option.path });
}
previousElement = element;
});
}
function createMobileSwitchEffect() {
let firstRun = true;
signals.createEffect(options.selected, () => {
if (!firstRun && !isHidden(asideLabelElement)) {
asideLabelElement.click();
}
firstRun = false;
});
}
createMobileSwitchEffect();
onFirstIntersection(asideElement, () =>
signals.runWithOwner(owner, initSelectedFrame),
);
}
initSelected();
});
onFirstIntersection(navElement, async () => {
options.parent.set(navElement);
function initSelected() {
let firstRun = true;
function initSelectedFrame() {
if (!firstRun) throw Error("Unreachable");
firstRun = false;
const option = options.selected();
if (!option) throw "Selected should be set by now";
const path = [...option.path];
let previousElement = /** @type {HTMLElement | undefined} */ (undefined);
let firstTimeLoadingChart = true;
/** @type {HTMLUListElement | null} */
let ul = /** @type {any} */ (null);
async function getFirstChild() {
try {
ul = /** @type {HTMLUListElement} */ (navElement.firstElementChild);
await next();
if (!ul) {
await getFirstChild();
options.selected.onChange((option) => {
/** @type {HTMLElement | undefined} */
let element;
switch (option.kind) {
case "chart": {
element = chartElement;
if (firstTimeLoadingChart) {
initChart(brk);
}
firstTimeLoadingChart = false;
setChartOption(option);
break;
}
} catch (_) {
await next();
await getFirstChild();
}
}
await getFirstChild();
if (!ul) throw Error("Unreachable");
while (path.length > 1) {
const name = path.shift();
if (!name) throw "Unreachable";
/** @type {HTMLDetailsElement[]} */
let detailsList = [];
while (!detailsList.length) {
detailsList = Array.from(ul.querySelectorAll(":scope > li > details"));
if (!detailsList.length) {
await next();
}
}
const details = detailsList.find((s) => s.dataset.name == name);
if (!details) return;
details.open = true;
ul = null;
while (!ul) {
const uls = /** @type {HTMLUListElement[]} */ (
Array.from(details.querySelectorAll(":scope > ul"))
);
if (!uls.length) {
await next();
} else if (uls.length > 1) {
throw "Shouldn't be possible";
} else {
ul = /** @type {HTMLUListElement} */ (uls.pop());
}
}
}
/** @type {HTMLAnchorElement[]} */
let anchors = [];
while (!anchors.length) {
anchors = Array.from(ul.querySelectorAll(":scope > li > a"));
if (!anchors.length) {
await next();
}
}
anchors
.find((a) => a.getAttribute("href") == window.document.location.pathname)
?.scrollIntoView({
behavior: "instant",
block: "center",
});
});
onFirstIntersection(searchElement, () => {
console.log("search: init");
const haystack = options.list.map((option) => option.title);
const RESULTS_PER_PAGE = 100;
/**
* @param {uFuzzy.SearchResult} searchResult
* @param {number} pageIndex
*/
function computeResultPage(searchResult, pageIndex) {
/** @type {{ option: Option, title: string }[]} */
let list = [];
let [indexes, _info, order] = searchResult || [null, null, null];
const minIndex = pageIndex * RESULTS_PER_PAGE;
if (indexes?.length) {
const maxIndex = Math.min(
(order || indexes).length - 1,
minIndex + RESULTS_PER_PAGE - 1,
);
list = Array(maxIndex - minIndex + 1);
for (let i = minIndex; i <= maxIndex; i++) {
let index = indexes[i];
const title = haystack[index];
list[i % 100] = {
option: options.list[index],
title,
};
}
}
return list;
}
/** @type {uFuzzy.Options} */
const config = {
intraIns: Infinity,
intraChars: `[a-z\d' ]`,
};
const fuzzyMultiInsert = /** @type {uFuzzy} */ (
ufuzzy({
intraIns: 1,
})
);
const fuzzyMultiInsertFuzzier = /** @type {uFuzzy} */ (ufuzzy(config));
const fuzzySingleError = /** @type {uFuzzy} */ (
ufuzzy({
intraMode: 1,
...config,
})
);
const fuzzySingleErrorFuzzier = /** @type {uFuzzy} */ (
ufuzzy({
intraMode: 1,
...config,
})
);
/** @type {VoidFunction | undefined} */
let dispose;
function inputEvent() {
signals.createRoot((_dispose) => {
const needle = /** @type {string} */ (searchInput.value);
dispose?.();
dispose = _dispose;
searchResultsElement.scrollTo({
top: 0,
});
if (!needle) {
searchResultsElement.innerHTML = "";
case "link": {
return;
}
}
const outOfOrder = 5;
const infoThresh = 5_000;
if (!element) throw "Element should be set";
let result = fuzzyMultiInsert?.search(
haystack,
needle,
undefined,
infoThresh,
);
if (element !== previousElement) {
if (previousElement) previousElement.hidden = true;
element.hidden = false;
}
if (!result?.[0]?.length || !result?.[1]) {
result = fuzzyMultiInsert?.search(
haystack,
needle,
outOfOrder,
infoThresh,
);
}
if (!previousElement) {
replaceHistory({ pathname: option.path });
}
if (!result?.[0]?.length || !result?.[1]) {
result = fuzzySingleError?.search(
haystack,
needle,
outOfOrder,
infoThresh,
);
}
previousElement = element;
});
}
if (!result?.[0]?.length || !result?.[1]) {
result = fuzzySingleErrorFuzzier?.search(
haystack,
needle,
outOfOrder,
infoThresh,
);
}
if (!result?.[0]?.length || !result?.[1]) {
result = fuzzyMultiInsertFuzzier?.search(
haystack,
needle,
undefined,
infoThresh,
);
}
if (!result?.[0]?.length || !result?.[1]) {
result = fuzzyMultiInsertFuzzier?.search(
haystack,
needle,
outOfOrder,
infoThresh,
);
}
searchResultsElement.innerHTML = "";
const list = computeResultPage(result, 0);
list.forEach(({ option, title }) => {
const li = window.document.createElement("li");
searchResultsElement.appendChild(li);
const element = options.createOptionElement({
option,
name: title,
});
if (element) {
li.append(element);
}
});
});
let firstMobileSwitch = true;
options.selected.onChange(() => {
if (!firstMobileSwitch && !isHidden(asideLabelElement)) {
asideLabelElement.click();
}
if (searchInput.value) {
inputEvent();
}
searchInput.addEventListener("input", inputEvent);
firstMobileSwitch = false;
});
function initDesktopResizeBar() {
const resizeBar = getElementById("resize-bar");
let resize = false;
let startingWidth = 0;
let startingClientX = 0;
onFirstIntersection(asideElement, initSelectedFrame);
}
initSelected();
const barWidthLocalStorageKey = "bar-width";
onFirstIntersection(navElement, async () => {
options.setParent(navElement);
/**
* @param {number | null} width
*/
function setBarWidth(width) {
// TODO: Check if should be a signal ??
try {
if (typeof width === "number") {
mainElement.style.width = `${width}px`;
writeToStorage(barWidthLocalStorageKey, String(width));
} else {
mainElement.style.width = style.getPropertyValue(
"--default-main-width",
);
removeStored(barWidthLocalStorageKey);
}
} catch (_) {}
const option = options.selected.value;
if (!option) throw "Selected should be set by now";
const path = [...option.path];
/** @type {HTMLUListElement | null} */
let ul = /** @type {any} */ (null);
async function getFirstChild() {
try {
ul = /** @type {HTMLUListElement} */ (navElement.firstElementChild);
await next();
if (!ul) {
await getFirstChild();
}
} catch (_) {
await next();
await getFirstChild();
}
}
await getFirstChild();
if (!ul) throw Error("Unreachable");
/**
* @param {MouseEvent} event
*/
function mouseMoveEvent(event) {
if (resize) {
setBarWidth(startingWidth + (event.clientX - startingClientX));
while (path.length > 1) {
const name = path.shift();
if (!name) throw "Unreachable";
/** @type {HTMLDetailsElement[]} */
let detailsList = [];
while (!detailsList.length) {
detailsList = Array.from(ul.querySelectorAll(":scope > li > details"));
if (!detailsList.length) {
await next();
}
}
const details = detailsList.find((s) => s.dataset.name == name);
if (!details) return;
details.open = true;
ul = null;
while (!ul) {
const uls = /** @type {HTMLUListElement[]} */ (
Array.from(details.querySelectorAll(":scope > ul"))
);
if (!uls.length) {
await next();
} else if (uls.length > 1) {
throw "Shouldn't be possible";
} else {
ul = /** @type {HTMLUListElement} */ (uls.pop());
}
}
resizeBar.addEventListener("mousedown", (event) => {
startingClientX = event.clientX;
startingWidth = mainElement.clientWidth;
resize = true;
window.document.documentElement.dataset.resize = "";
window.addEventListener("mousemove", mouseMoveEvent);
});
resizeBar.addEventListener("dblclick", () => {
setBarWidth(null);
});
const setResizeFalse = () => {
resize = false;
delete window.document.documentElement.dataset.resize;
window.removeEventListener("mousemove", mouseMoveEvent);
};
window.addEventListener("mouseup", setResizeFalse);
window.addEventListener("mouseleave", setResizeFalse);
}
initDesktopResizeBar();
/** @type {HTMLAnchorElement[]} */
let anchors = [];
while (!anchors.length) {
anchors = Array.from(ul.querySelectorAll(":scope > li > a"));
if (!anchors.length) {
await next();
}
}
anchors
.find((a) => a.getAttribute("href") == window.document.location.pathname)
?.scrollIntoView({
behavior: "instant",
block: "center",
});
});
onFirstIntersection(searchElement, () => {
initSearch(options);
});
function initDesktopResizeBar() {
const resizeBar = getElementById("resize-bar");
let resize = false;
let startingWidth = 0;
let startingClientX = 0;
const barWidthLocalStorageKey = "bar-width";
/**
* @param {number | null} width
*/
function setBarWidth(width) {
// TODO: Check if should be a signal ??
try {
if (typeof width === "number") {
mainElement.style.width = `${width}px`;
writeToStorage(barWidthLocalStorageKey, String(width));
} else {
mainElement.style.width = style.getPropertyValue(
"--default-main-width",
);
removeStored(barWidthLocalStorageKey);
}
} catch (_) {}
}
/**
* @param {MouseEvent} event
*/
function mouseMoveEvent(event) {
if (resize) {
setBarWidth(startingWidth + (event.clientX - startingClientX));
}
}
resizeBar.addEventListener("mousedown", (event) => {
startingClientX = event.clientX;
startingWidth = mainElement.clientWidth;
resize = true;
window.document.documentElement.dataset.resize = "";
window.addEventListener("mousemove", mouseMoveEvent);
});
resizeBar.addEventListener("dblclick", () => {
setBarWidth(null);
});
const setResizeFalse = () => {
resize = false;
delete window.document.documentElement.dataset.resize;
window.removeEventListener("mousemove", mouseMoveEvent);
};
window.addEventListener("mouseup", setResizeFalse);
window.addEventListener("mouseleave", setResizeFalse);
}
initDesktopResizeBar();