web: fix error in lockdown safari + charts: update instead of setData when possible

This commit is contained in:
nym21
2025-06-16 18:20:56 +02:00
parent 098f6de047
commit 985e961876
9 changed files with 262 additions and 216 deletions
Generated
+2 -5
View File
@@ -3683,12 +3683,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
[[package]]
name = "smallvec"
+6 -4
View File
@@ -49,10 +49,12 @@ pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> i
let mut contents = fs::read_to_string(&absolute_source_index_path).unwrap();
if let Ok(entry) = fs::read_to_string(absolute_dist_path_clone.join("scripts/entry.js")) {
let start = entry.find("main").unwrap();
let end = entry.find(".js").unwrap();
let main_hashed = &entry[start..end];
contents = contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
if let Some(start) = entry.find("main") {
if let Some(end) = entry.find(".js") {
let main_hashed = &entry[start..end];
contents = contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
}
}
}
let _ = fs::write(&absolute_dist_index_path, contents);
+6 -7
View File
@@ -61,9 +61,12 @@ export const VERSION = \"v{}\";
.join(" | ")
);
contents += "\n\nexport function createVecIdToIndexes() {\n";
contents += "\n\n/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes */";
contents += "\n/** @typedef {keyof VecIdToIndexes} VecId */\n";
contents += " return /** @type {const} */ ({\n";
contents += "\nexport function createVecIdToIndexes() {\n";
contents += " return {\n";
self.vec_trees
.id_to_index_to_vec
@@ -79,11 +82,7 @@ export const VERSION = \"v{}\";
contents += &format!(" \"{id}\": [{indexes}],\n");
});
contents += " });\n";
contents.push('}');
contents += "\n/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes */";
contents += "\n/** @typedef {keyof VecIdToIndexes} VecId */\n";
contents += " };\n}\n";
fs::write(path, contents)
}
+16 -12
View File
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
@@ -1375,7 +1375,7 @@
// @ts-check
const preferredColorSchemeMatchMedia = window.matchMedia(
"(prefers-color-scheme: dark)",
"(prefers-color-scheme: dark)"
);
const themeColor = window.document.createElement("meta");
@@ -1385,7 +1385,7 @@
/** @param {boolean} dark */
function updateThemeColor(dark) {
const theme = getComputedStyle(
window.document.documentElement,
window.document.documentElement
).getPropertyValue(dark ? "--black" : "--white");
themeColor.content = theme;
}
@@ -1395,7 +1395,7 @@
"change",
({ matches }) => {
updateThemeColor(matches);
},
}
);
if ("standalone" in window.navigator && !!window.navigator.standalone) {
@@ -1404,7 +1404,9 @@
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("/service-worker.js");
navigator.serviceWorker.register("/service-worker.js", {
scope: "/",
});
});
}
</script>
@@ -1852,13 +1854,15 @@
</div>
<script>
// Prevent width jumping
const savedWidth = localStorage.getItem("bar-width");
if (savedWidth) {
const main = window.document.getElementById("main");
if (!main) throw "Should exist";
main.style.width = `${savedWidth}px`;
}
try {
// Prevent width jumping
const savedWidth = localStorage.getItem("bar-width");
if (savedWidth) {
const main = window.document.getElementById("main");
if (!main) throw "Should exist";
main.style.width = `${savedWidth}px`;
}
} catch (_) {}
</script>
</body>
</html>
@@ -24,10 +24,10 @@
* @property {Signal<string | null>} url
* @property {VoidFunction} remove
*
* @typedef {ChartData<_SingleValueData<number>>} SingleValueData
* @typedef {ChartData<_CandlestickData<number>>} CandlestickData
* @typedef {ChartData<_LineData<number>>} LineData
* @typedef {ChartData<_BaselineData<number>>} BaselineData
* @typedef {_SingleValueData<number>} SingleValueData
* @typedef {_CandlestickData<number>} CandlestickData
* @typedef {_LineData<number>} LineData
* @typedef {_BaselineData<number>} BaselineData
*
* @typedef {function({ iseries: ISeries; unit: Unit; index: Index }): void} SetDataCallback
*
@@ -44,11 +44,6 @@
* @typedef {BaselineSeriesPartialOptions & PartialCreatePriceLineOptions} PartialBaselineStyleOptions
*/
/**
* @template T
* @typedef {T & Valued} ChartData<T>
*/
import {
createChart,
CandlestickSeries,
@@ -146,7 +141,7 @@ function createChartElement({
}
: {}),
// ..._options,
}),
})
);
ichart.priceScale("right").applyOptions({
@@ -178,7 +173,7 @@ function createChartElement({
},
},
});
},
}
);
let timeScaleSet = false;
@@ -190,12 +185,12 @@ function createChartElement({
index === /** @satisfies {MonthIndex} */ (7)
? 1
: index === /** @satisfies {QuarterIndex} */ (19)
? 3
: index === /** @satisfies {YearIndex} */ (23)
? 12
: index === /** @satisfies {DecadeIndex} */ (1)
? 120
: 0.5;
? 3
: index === /** @satisfies {YearIndex} */ (23)
? 12
: index === /** @satisfies {DecadeIndex} */ (1)
? 120
: 0.5;
ichart.applyOptions({
timeScale: {
@@ -218,7 +213,7 @@ function createChartElement({
activeResources.forEach((v) => {
v.fetch();
});
}),
})
);
if (fitContent) {
@@ -249,8 +244,7 @@ function createChartElement({
const children = Array.from(parent.childNodes).filter(
(element) =>
/** @type {HTMLElement} */ (element).dataset.position ===
position,
/** @type {HTMLElement} */ (element).dataset.position === position
);
if (children.length === 1) {
@@ -272,7 +266,7 @@ function createChartElement({
fieldset.append(createChild(pane));
}),
paneIndex ? 50 : 0,
paneIndex ? 50 : 0
);
}
@@ -356,7 +350,7 @@ function createChartElement({
// Or remove ?
iseries.applyOptions({
visible: active,
}),
})
);
iseries.setSeriesOrder(order);
@@ -387,7 +381,7 @@ function createChartElement({
index,
index === /** @satisfies {Height} */ (5)
? "timestamp-fixed"
: "timestamp",
: "timestamp"
);
timeResource.fetch();
@@ -403,18 +397,18 @@ function createChartElement({
const fetchedKey = vecsResources.defaultFetchedKey;
signals.createEffect(
() => [
timeResource.fetched().get(fetchedKey)?.vec(),
valuesResource.fetched().get(fetchedKey)?.vec(),
],
([indexes, _ohlcs]) => {
if (!indexes?.length || !_ohlcs?.length) return;
() => ({
_indexes: timeResource.fetched().get(fetchedKey)?.vec(),
values: valuesResource.fetched().get(fetchedKey)?.vec(),
}),
({ _indexes, values }) => {
if (!_indexes?.length || !values?.length) return;
// const seriesData = series.inner.data();
// const set = seriesData.length === 0;
const indexes = /** @type {number[]} */ (_indexes);
const ohlcs = /** @type {OHLCTuple[]} */ (_ohlcs);
let length = Math.min(indexes.length, ohlcs.length);
let length = Math.min(indexes.length, values.length);
/** @type {LineData[] | CandlestickData[]} */
const data = new Array(length);
let prevTime = null;
let timeOffset = 0;
@@ -425,7 +419,7 @@ function createChartElement({
if (sameTime) {
timeOffset += 1;
}
const v = ohlcs[i];
const v = values[i];
const offsetedI = i - timeOffset;
if (v === null) {
data[offsetedI] = {
@@ -441,16 +435,16 @@ function createChartElement({
if (sameTime) {
console.log(data[offsetedI]);
}
// const prev = sameTime ? data[offsetedI] : undefined;
const candles = /** @type {CandlestickData[]} */ (data);
let [open, high, low, close] = v;
data[offsetedI] = {
candles[offsetedI] = {
time,
open: sameTime ? data[offsetedI].open : open,
open: sameTime ? candles[offsetedI].open : open,
high: sameTime
? Math.max(data[offsetedI].high, high)
? Math.max(candles[offsetedI].high, high)
: high,
low: sameTime
? Math.min(data[offsetedI].low, low)
? Math.min(candles[offsetedI].low, low)
: low,
close,
};
@@ -460,20 +454,64 @@ function createChartElement({
data.length -= timeOffset;
// if (set) {
iseries.setData(data);
if (fitContent) {
ichart.timeScale().fitContent();
}
// } else {
// let seriesDataOffset = 0;
// while seriesData
// data.forEach((bar) => {
// iseries.update(bar, true);
// });
// }
hasData.set(true);
const seriesData = series.inner.data();
if (!seriesData.length) {
console.log("set: vecid:", vecId);
iseries.setData(data);
if (fitContent) {
ichart.timeScale().fitContent();
}
} else if (data.length) {
let i = 0;
const first = seriesData[0];
while (data[i].time < first.time) {
iseries.update(data[i], true);
i++;
}
const last = seriesData.at(-1);
if (!last) throw Error("Unreachable");
let j = 0;
while (i < data.length) {
const dataI = data[i];
const iTime = dataI.time;
const seriesDataJ = seriesData[j];
const jTime = seriesDataJ.time;
if (iTime === jTime) {
const historicalUpdate = iTime < last.time;
if ("value" in dataI) {
// @ts-ignore
if (dataI.value !== seriesDataJ.value) {
iseries.update(dataI, historicalUpdate);
}
} else if (
// @ts-ignore
dataI.open !== seriesDataJ.open ||
// @ts-ignore
dataI.high !== seriesDataJ.high ||
// @ts-ignore
dataI.low !== seriesDataJ.low ||
// @ts-ignore
dataI.close !== seriesDataJ.close
) {
iseries.update(dataI, historicalUpdate);
}
i++;
} else if (iTime < jTime) {
iseries.update(dataI, true);
i++;
} else if (iTime > last.time) {
iseries.update(dataI);
i++;
} else if (iTime > jTime) {
j++;
}
}
}
setDataCallback?.({
iseries,
index,
@@ -494,7 +532,7 @@ function createChartElement({
}
});
timeScaleSet = true;
},
}
);
} else {
activeResources.delete(valuesResource);
@@ -587,7 +625,7 @@ function createChartElement({
borderVisible: false,
visible: defaultActive !== false,
},
paneIndex,
paneIndex
)
);
@@ -643,7 +681,7 @@ function createChartElement({
color: color(),
...options,
},
paneIndex,
paneIndex
)
);
@@ -711,7 +749,7 @@ function createChartElement({
topFillColor2: "transparent",
lineVisible: true,
},
paneIndex,
paneIndex
)
);
@@ -874,7 +912,7 @@ function createLegend({ signals, utils }) {
} else {
spanColor.style.backgroundColor = tameColor(color);
}
},
}
);
});
@@ -1034,17 +1072,17 @@ function numberToShortUSFormat(value, digits) {
if (modulused === 0) {
return `${numberToUSFormat(
value / (1_000_000 * 1_000 ** letterIndex),
3,
3
)}${letter}`;
} else if (modulused === 1) {
return `${numberToUSFormat(
value / (1_000_000 * 1_000 ** letterIndex),
2,
2
)}${letter}`;
} else {
return `${numberToUSFormat(
value / (1_000_000 * 1_000 ** letterIndex),
1,
1
)}${letter}`;
}
}
@@ -1094,7 +1132,7 @@ function createOklchToRGBA() {
return rgb.map((c) =>
Math.abs(c) > 0.0031308
? (c < 0 ? -1 : 1) * (1.055 * Math.abs(c) ** (1 / 2.4) - 0.055)
: 12.92 * c,
: 12.92 * c
);
}
/**
@@ -1106,7 +1144,7 @@ function createOklchToRGBA() {
1, 0.3963377773761749, 0.2158037573099136, 1, -0.1055613458156586,
-0.0638541728258133, 1, -0.0894841775298119, -1.2914855480194092,
]),
lab,
lab
);
const LMS = /** @type {[number, number, number]} */ (
LMSg.map((val) => val ** 3)
@@ -1117,7 +1155,7 @@ function createOklchToRGBA() {
-0.0405757452148008, 1.112286803280317, -0.0717110580655164,
-0.0763729366746601, -0.4214933324022432, 1.5869240198367816,
]),
LMS,
LMS
);
}
/**
@@ -1130,7 +1168,7 @@ function createOklchToRGBA() {
-0.9692436362808796, 1.8759675015077202, 0.04155505740717559,
0.05563007969699366, -0.20397695888897652, 1.0569715142428786,
],
xyz,
xyz
);
}
@@ -1153,8 +1191,8 @@ function createOklchToRGBA() {
});
const rgb = srgbLinear2rgb(
xyz2rgbLinear(
oklab2xyz(oklch2oklab(/** @type {[number, number, number]} */ (lch))),
),
oklab2xyz(oklch2oklab(/** @type {[number, number, number]} */ (lch)))
)
).map((v) => {
return Math.max(Math.min(Math.round(v * 255), 255), 0);
});
@@ -75,7 +75,7 @@ const signals = {
createSignal(initialValue, options) {
const [get, set] = this.createSolidSignal(
/** @type {any} */ (initialValue),
options,
options
);
// @ts-ignore
@@ -94,7 +94,7 @@ const signals = {
typeof save.keyPrefix === "string"
? save.keyPrefix
: save.keyPrefix()
}-${paramKey}`,
}-${paramKey}`
);
let serialized = /** @type {string | null} */ (null);
@@ -102,7 +102,9 @@ const signals = {
serialized = new URLSearchParams(window.location.search).get(paramKey);
}
if (serialized === null) {
serialized = localStorage.getItem(storageKey());
try {
serialized = localStorage.getItem(storageKey());
} catch (_) {}
}
if (serialized) {
set(() => (serialized ? save.deserialize(serialized) : initialValue));
@@ -111,8 +113,12 @@ const signals = {
let firstRun1 = true;
this.createEffect(storageKey, (storageKey) => {
if (!firstRun1) {
serialized = localStorage.getItem(storageKey);
set(() => (serialized ? save.deserialize(serialized) : initialValue));
try {
serialized = localStorage.getItem(storageKey);
set(() =>
serialized ? save.deserialize(serialized) : initialValue
);
} catch (_) {}
}
firstRun1 = false;
});
@@ -122,17 +128,19 @@ const signals = {
if (!save) return;
if (!firstRun2) {
if (
value !== undefined &&
value !== null &&
(initialValue === undefined ||
initialValue === null ||
save.serialize(value) !== save.serialize(initialValue))
) {
localStorage.setItem(storageKey(), save.serialize(value));
} else {
localStorage.removeItem(storageKey());
}
try {
if (
value !== undefined &&
value !== null &&
(initialValue === undefined ||
initialValue === null ||
save.serialize(value) !== save.serialize(initialValue))
) {
localStorage.setItem(storageKey(), save.serialize(value));
} else {
localStorage.removeItem(storageKey());
}
} catch (_) {}
}
if (
@@ -174,7 +182,7 @@ function writeParam(key, value) {
window.history.replaceState(
null,
"",
`${window.location.pathname}?${urlParams.toString()}`,
`${window.location.pathname}?${urlParams.toString()}`
);
} catch (_) {}
}
+69 -61
View File
@@ -1,8 +1,8 @@
// @ts-check
/**
* @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, ChartableIndex, SeriesType } from "./options"
* @import { Valued, SingleValueData, CandlestickData, ChartData, OHLCTuple, Series, ISeries, LineData, BaselineData, PartialLineStyleOptions, PartialBaselineStyleOptions, PartialCandlestickStyleOptions } from "../packages/lightweight-charts/wrapper"
* @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType } from "./options"
* @import { Valued, SingleValueData, CandlestickData, OHLCTuple, Series, ISeries, LineData, BaselineData, PartialLineStyleOptions, PartialBaselineStyleOptions, PartialCandlestickStyleOptions } from "../packages/lightweight-charts/wrapper"
* @import * as _ from "../packages/ufuzzy/v1.0.18/types"
* @import { Signal, Signals, Accessor } from "../packages/solid-signals/wrapper";
* @import { DateIndex, DecadeIndex, DifficultyEpoch, Index, HalvingEpoch, Height, MonthIndex, P2PK33Index, P2PK65Index, P2PKHIndex, P2SHIndex, P2MSIndex, P2AIndex, P2TRIndex, P2WPKHIndex, P2WSHIndex, TxIndex, InputIndex, OutputIndex, VecId, WeekIndex, YearIndex, VecIdToIndexes, QuarterIndex, EmptyOutputIndex, OpReturnIndex, UnknownOutputIndex } from "./vecid-to-indexes"
@@ -63,14 +63,14 @@ function initPackages() {
const imports = {
async signals() {
return import("../packages/solid-signals/wrapper.js").then(
(d) => d.default,
(d) => d.default
);
},
async lightweightCharts() {
return window.document.fonts.ready.then(() =>
import("../packages/lightweight-charts/wrapper.js").then(
(d) => d.default,
),
(d) => d.default
)
);
},
async leanQr() {
@@ -78,7 +78,7 @@ function initPackages() {
},
async ufuzzy() {
return import("../packages/ufuzzy/v1.0.18/script.js").then(
({ default: d }) => d,
({ default: d }) => d
);
},
};
@@ -585,7 +585,7 @@ function createUtils() {
window.history.pushState(
null,
"",
`${pathname}?${urlParams.toString()}`,
`${pathname}?${urlParams.toString()}`
);
} catch (_) {}
},
@@ -602,7 +602,7 @@ function createUtils() {
window.history.replaceState(
null,
"",
`${pathname}?${urlParams.toString()}`,
`${pathname}?${urlParams.toString()}`
);
} catch (_) {}
},
@@ -988,16 +988,22 @@ function createUtils() {
* @param {string} key
*/
read(key) {
return localStorage.getItem(key);
try {
return localStorage.getItem(key);
} catch (_) {
return null;
}
},
/**
* @param {string} key
* @param {string | boolean | null | undefined} value
*/
write(key, value) {
value !== undefined && value !== null
? localStorage.setItem(key, String(value))
: localStorage.removeItem(key);
try {
value !== undefined && value !== null
? localStorage.setItem(key, String(value))
: localStorage.removeItem(key);
} catch (_) {}
},
/**
* @param {string} key
@@ -1185,7 +1191,7 @@ function createUtils() {
},
/**
* @param {string} v
* @returns {ChartableIndex}
* @returns {Index}
*/
deserialize(v) {
switch (v) {
@@ -1204,7 +1210,7 @@ function createUtils() {
case "decade":
return /** @satisfies {DecadeIndex} */ (1);
default:
throw Error("Unsupported");
throw Error("todo");
}
},
},
@@ -1235,8 +1241,8 @@ function createUtils() {
today.getUTCDate(),
0,
0,
0,
),
0
)
);
},
/**
@@ -1329,7 +1335,7 @@ function createUtils() {
*/
function getNumberOfDaysBetweenTwoDates(oldest, youngest) {
return Math.round(
Math.abs((youngest.getTime() - oldest.getTime()) / date.ONE_DAY_IN_MS),
Math.abs((youngest.getTime() - oldest.getTime()) / date.ONE_DAY_IN_MS)
);
}
@@ -1547,7 +1553,7 @@ function createVecsResources(signals, utils) {
const fetchedRecord = signals.createSignal(
/** @type {Map<string, {loading: boolean, at: Date | null, vec: Signal<T[] | null>}>} */ (
new Map()
),
)
);
return {
@@ -1595,7 +1601,7 @@ function createVecsResources(signals, utils) {
index,
id,
from,
to,
to
)
);
fetched.at = new Date();
@@ -1856,7 +1862,7 @@ function initWebSockets(signals, utils) {
window.document.addEventListener(
"visibilitychange",
reinitWebSocketIfDocumentNotHidden,
reinitWebSocketIfDocumentNotHidden
);
window.document.addEventListener("online", reinitWebSocket);
@@ -1865,7 +1871,7 @@ function initWebSockets(signals, utils) {
ws?.close();
window.document.removeEventListener(
"visibilitychange",
reinitWebSocketIfDocumentNotHidden,
reinitWebSocketIfDocumentNotHidden
);
window.document.removeEventListener("online", reinitWebSocket);
live.set(false);
@@ -1891,7 +1897,7 @@ function initWebSockets(signals, utils) {
symbol: ["BTC/USD"],
interval: 1440,
},
}),
})
);
});
@@ -1910,7 +1916,6 @@ function initWebSockets(signals, utils) {
high: Number(high),
low: Number(low),
close: Number(close),
value: Number(close),
};
candle && callback({ ...candle });
@@ -1921,7 +1926,7 @@ function initWebSockets(signals, utils) {
/** @type {ReturnType<typeof createWebsocket<CandlestickData>>} */
const kraken1dCandle = createWebsocket((callback) =>
krakenCandleWebSocketCreator(callback),
krakenCandleWebSocketCreator(callback)
);
kraken1dCandle.open();
@@ -1980,7 +1985,7 @@ function main() {
}
const frame = window.document.getElementById(
/** @type {string} */ (input.value),
/** @type {string} */ (input.value)
);
if (!frame) {
@@ -2078,23 +2083,23 @@ function main() {
function initDark() {
const preferredColorSchemeMatchMedia = window.matchMedia(
"(prefers-color-scheme: dark)",
"(prefers-color-scheme: dark)"
);
const dark = signals.createSignal(
preferredColorSchemeMatchMedia.matches,
preferredColorSchemeMatchMedia.matches
);
preferredColorSchemeMatchMedia.addEventListener(
"change",
({ matches }) => {
dark.set(matches);
},
}
);
return dark;
}
const dark = initDark();
const qrcode = signals.createSignal(
/** @type {string | null} */ (null),
/** @type {string | null} */ (null)
);
function createLastHeightResource() {
@@ -2105,7 +2110,7 @@ function main() {
lastHeight.set(h);
},
/** @satisfies {Height} */ (5),
"height",
"height"
);
}
fetchLastHeight();
@@ -2149,10 +2154,10 @@ function main() {
const owner = signals.getOwner();
const chartOption = signals.createSignal(
/** @type {ChartOption | null} */ (null),
/** @type {ChartOption | null} */ (null)
);
const simOption = signals.createSignal(
/** @type {SimulationOption | null} */ (null),
/** @type {SimulationOption | null} */ (null)
);
let previousElement = /** @type {HTMLElement | undefined} */ (
@@ -2198,9 +2203,9 @@ function main() {
webSockets,
vecsResources,
vecIdToIndexes,
}),
),
),
})
)
)
);
}
firstTimeLoadingChart = false;
@@ -2221,8 +2226,8 @@ function main() {
vecsResources,
option,
vecIdToIndexes,
}),
),
})
)
);
}
firstTimeLoadingTable = false;
@@ -2246,9 +2251,9 @@ function main() {
signals,
utils,
vecsResources,
}),
),
),
})
)
)
);
}
firstTimeLoadingSimulation = false;
@@ -2277,7 +2282,7 @@ function main() {
createMobileSwitchEffect();
utils.dom.onFirstIntersection(elements.aside, () =>
signals.runWithOwner(owner, initSelectedFrame),
signals.runWithOwner(owner, initSelectedFrame)
);
}
initSelected();
@@ -2355,7 +2360,7 @@ function main() {
if (indexes?.length) {
const maxIndex = Math.min(
(order || indexes).length - 1,
minIndex + RESULTS_PER_PAGE - 1,
minIndex + RESULTS_PER_PAGE - 1
);
list = Array(maxIndex - minIndex + 1);
@@ -2431,7 +2436,7 @@ function main() {
haystack,
needle,
undefined,
infoThresh,
infoThresh
);
if (!result?.[0]?.length || !result?.[1]) {
@@ -2439,7 +2444,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2448,7 +2453,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2457,7 +2462,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2466,7 +2471,7 @@ function main() {
haystack,
needle,
undefined,
infoThresh,
infoThresh
);
}
@@ -2475,7 +2480,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2558,7 +2563,7 @@ function main() {
shareDiv.hidden = false;
});
}),
})
);
}
initShare();
@@ -2575,15 +2580,18 @@ function main() {
* @param {number | null} width
*/
function setBarWidth(width) {
if (typeof width === "number") {
elements.main.style.width = `${width}px`;
localStorage.setItem(barWidthLocalStorageKey, String(width));
} else {
elements.main.style.width = elements.style.getPropertyValue(
"--default-main-width",
);
localStorage.removeItem(barWidthLocalStorageKey);
}
// TODO: Check if should be a signal ??
try {
if (typeof width === "number") {
elements.main.style.width = `${width}px`;
utils.storage.write(barWidthLocalStorageKey, String(width));
} else {
elements.main.style.width = elements.style.getPropertyValue(
"--default-main-width"
);
utils.storage.remove(barWidthLocalStorageKey);
}
} catch (_) {}
}
/**
@@ -2616,9 +2624,9 @@ function main() {
window.addEventListener("mouseleave", setResizeFalse);
}
initDesktopResizeBar();
}),
),
),
})
)
)
);
}
main();
+28 -39
View File
@@ -1,16 +1,5 @@
// @ts-check
/**
* @typedef {Height | DateIndex | WeekIndex | MonthIndex | QuarterIndex | YearIndex | DecadeIndex} ChartableIndex
*/
/**
* @template {readonly unknown[]} T
* @typedef {Extract<T[number], ChartableIndex> extends never ? false : true} IncludesChartableIndex
*/
/**
* @typedef {{[K in VecId]: IncludesChartableIndex<VecIdToIndexes[K]> extends true ? K : never}[VecId]} ChartableVecId
*/
/**
* @typedef {Object} BaseSeriesBlueprint
* @property {string} title
@@ -42,7 +31,7 @@
*
* @typedef {AnySeriesBlueprint["type"]} SeriesType
*
* @typedef {{ key: ChartableVecId, unit?: Unit | Unit[] }} FetchedAnySeriesOptions
* @typedef {{ key: VecId, unit?: Unit | Unit[] }} FetchedAnySeriesOptions
*
* @typedef {BaselineSeriesBlueprint & FetchedAnySeriesOptions} FetchedBaselineSeriesBlueprint
* @typedef {CandlestickSeriesBlueprint & FetchedAnySeriesOptions} FetchedCandlestickSeriesBlueprint
@@ -122,11 +111,11 @@
function createPartialOptions(colors) {
/**
* @template {string} S
* @typedef {Extract<ChartableVecId, `${S}${string}`>} StartsWith
* @typedef {Extract<VecId, `${S}${string}`>} StartsWith
*/
/**
* @template {string} S
* @typedef {Extract<ChartableVecId, `${string}${S}`>} EndsWith
* @typedef {Extract<VecId, `${string}${S}`>} EndsWith
*/
/**
* @template {string} K
@@ -813,7 +802,7 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {ChartableVecId} args.key
* @param {VecId} args.key
* @param {string} args.name
* @param {Color} [args.color]
* @param {boolean} [args.defaultActive]
@@ -925,7 +914,7 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {ChartableVecId & VecIdAverageBase & VecIdSumBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
* @param {VecId & VecIdAverageBase & VecIdSumBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
* @param {string} args.name
*/
function createBaseAverageSumCumulativeMinMaxPercentilesSeries({
@@ -943,7 +932,7 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {ChartableVecId & VecIdSumBase & CumulativeVecIdBase} args.key
* @param {VecId & VecIdSumBase & CumulativeVecIdBase} args.key
* @param {string} args.name
*/
function createBaseSumCumulativeSeries({ key, name }) {
@@ -1424,7 +1413,7 @@ function createPartialOptions(colors) {
key: `${fixKey(key)}realized-price`,
name,
color,
}),
})
),
}
: createPriceWithRatio({
@@ -1507,7 +1496,7 @@ function createPartialOptions(colors) {
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
key
)}net-realized-profit-and-loss-relative-to-realized-cap`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
@@ -1578,7 +1567,7 @@ function createPartialOptions(colors) {
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
key
)}adjusted-spent-output-profit-ratio`,
title: useGroupName ? name : "asopr",
color: useGroupName ? color : undefined,
@@ -1601,7 +1590,7 @@ function createPartialOptions(colors) {
key: `${fixKey(key)}sell-side-risk-ratio`,
name: useGroupName ? name : "Risk",
color: color,
}),
})
),
},
],
@@ -1690,7 +1679,7 @@ function createPartialOptions(colors) {
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
key
)}net-unrealized-profit-and-loss-relative-to-market-cap`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
@@ -1868,7 +1857,7 @@ function createPartialOptions(colors) {
key: `${key}-sma`,
name: key,
color,
}),
})
),
},
...averages.map(({ key, name, color }) =>
@@ -1878,7 +1867,7 @@ function createPartialOptions(colors) {
title: `${name} Market Price Moving Average`,
legend: "average",
color,
}),
})
),
],
},
@@ -1969,7 +1958,7 @@ function createPartialOptions(colors) {
},
}),
],
}),
})
),
.../** @type {const} */ ([
{ name: "2 Year", key: "2y" },
@@ -2040,7 +2029,7 @@ function createPartialOptions(colors) {
},
}),
],
}),
})
),
],
},
@@ -2056,7 +2045,7 @@ function createPartialOptions(colors) {
name: `${year}`,
color,
defaultActive,
}),
})
),
},
...dcaClasses.map(
@@ -2083,7 +2072,7 @@ function createPartialOptions(colors) {
},
}),
],
}),
})
),
],
},
@@ -2144,10 +2133,10 @@ function createPartialOptions(colors) {
bottom: [
...createAverageSumCumulativeMinMaxPercentilesSeries("fee"),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee-in-btc",
"fee-in-btc"
),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee-in-usd",
"fee-in-usd"
),
],
},
@@ -2889,7 +2878,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
const LS_SELECTED_KEY = `selected-id`;
const urlSelected = utils.url.pathnameToSelectedId();
const savedSelectedId = localStorage.getItem(LS_SELECTED_KEY);
const savedSelectedId = utils.storage.read(LS_SELECTED_KEY);
/** @type {Signal<Option>} */
const selected = signals.createSignal(/** @type {any} */ (undefined));
@@ -2903,7 +2892,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
const detailsList = [];
const treeElement = signals.createSignal(
/** @type {HTMLDivElement | null} */ (null),
/** @type {HTMLDivElement | null} */ (null)
);
/** @type {string[] | undefined} */
@@ -2973,7 +2962,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
signals.createEffect(selected, (selected) => {
if (selected?.id === option.id) {
input.checked = true;
localStorage.setItem(LS_SELECTED_KEY, option.id);
utils.storage.write(LS_SELECTED_KEY, option.id);
} else if (input.checked) {
input.checked = false;
}
@@ -3015,7 +3004,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
return null;
}
},
null,
null
);
partialTree.forEach((anyPartial, partialIndex) => {
@@ -3038,7 +3027,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
if ("tree" in anyPartial) {
const folderId = utils.stringToId(
`${(path || []).join(" ")} ${anyPartial.name} folder`,
`${(path || []).join(" ")} ${anyPartial.name} folder`
);
/** @type {Omit<OptionsGroup, keyof PartialOptionsGroup>} */
@@ -3053,13 +3042,13 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
const thisPath = groupAddons.id;
const passedDetails = signals.createSignal(
/** @type {HTMLDivElement | HTMLDetailsElement | null} */ (null),
/** @type {HTMLDivElement | HTMLDetailsElement | null} */ (null)
);
const childOptionsCount = recursiveProcessPartialTree(
anyPartial.tree,
passedDetails,
[...(path || []), thisPath],
[...(path || []), thisPath]
);
listForSum.push(childOptionsCount);
@@ -3191,7 +3180,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
});
return signals.createMemo(() =>
listForSum.reduce((acc, s) => acc + s(), 0),
listForSum.reduce((acc, s) => acc + s(), 0)
);
}
recursiveProcessPartialTree(partialOptions, treeElement);
@@ -3218,7 +3207,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
console.log(
[...m.entries()]
.filter(([_, value]) => value > 1)
.map(([key, _]) => key),
.map(([key, _]) => key)
);
throw Error("ID duplicate");
+6 -5
View File
@@ -2,7 +2,7 @@
// File auto-generated, any modifications will be overwritten
//
export const VERSION = "v0.0.58";
export const VERSION = "v0.0.61";
/** @typedef {0} DateIndex */
/** @typedef {1} DecadeIndex */
@@ -31,8 +31,11 @@ export const VERSION = "v0.0.58";
/** @typedef {DateIndex | DecadeIndex | DifficultyEpoch | EmptyOutputIndex | HalvingEpoch | Height | InputIndex | MonthIndex | OpReturnIndex | OutputIndex | P2AIndex | P2MSIndex | P2PK33Index | P2PK65Index | P2PKHIndex | P2SHIndex | P2TRIndex | P2WPKHIndex | P2WSHIndex | QuarterIndex | TxIndex | UnknownOutputIndex | WeekIndex | YearIndex} Index */
/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes */
/** @typedef {keyof VecIdToIndexes} VecId */
export function createVecIdToIndexes() {
return /** @type {const} */ ({
return {
"0": [0, 1, 2, 5, 7, 19, 22, 23],
"0sats-adjusted-spent-output-profit-ratio": [0],
"0sats-adjusted-value-created": [0, 1, 2, 5, 7, 19, 22, 23],
@@ -9037,7 +9040,5 @@ export function createVecIdToIndexes() {
"weight": [5, 20],
"yearindex": [7, 23],
"yearindex-count": [1],
});
};
}
/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes */
/** @typedef {keyof VecIdToIndexes} VecId */