diff --git a/Cargo.lock b/Cargo.lock index 5fc1f11ab..af24d2a87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/crates/brk_bundler/src/lib.rs b/crates/brk_bundler/src/lib.rs index 3b5f57749..f00f4b609 100644 --- a/crates/brk_bundler/src/lib.rs +++ b/crates/brk_bundler/src/lib.rs @@ -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); diff --git a/crates/brk_server/src/api/query/bridge.rs b/crates/brk_server/src/api/query/bridge.rs index b5c28e683..7a5e55e63 100644 --- a/crates/brk_server/src/api/query/bridge.rs +++ b/crates/brk_server/src/api/query/bridge.rs @@ -61,9 +61,12 @@ export const VERSION = \"v{}\"; .join(" | ") ); - contents += "\n\nexport function createVecIdToIndexes() {\n"; + contents += "\n\n/** @typedef {ReturnType} 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} VecIdToIndexes */"; - contents += "\n/** @typedef {keyof VecIdToIndexes} VecId */\n"; + contents += " };\n}\n"; fs::write(path, contents) } diff --git a/websites/default/index.html b/websites/default/index.html index 5bee7c11f..960292540 100644 --- a/websites/default/index.html +++ b/websites/default/index.html @@ -1,4 +1,4 @@ - + @@ -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: "/", + }); }); } @@ -1852,13 +1854,15 @@ diff --git a/websites/default/packages/lightweight-charts/wrapper.js b/websites/default/packages/lightweight-charts/wrapper.js index 8847371b5..5490397f2 100644 --- a/websites/default/packages/lightweight-charts/wrapper.js +++ b/websites/default/packages/lightweight-charts/wrapper.js @@ -24,10 +24,10 @@ * @property {Signal} url * @property {VoidFunction} remove * - * @typedef {ChartData<_SingleValueData>} SingleValueData - * @typedef {ChartData<_CandlestickData>} CandlestickData - * @typedef {ChartData<_LineData>} LineData - * @typedef {ChartData<_BaselineData>} BaselineData + * @typedef {_SingleValueData} SingleValueData + * @typedef {_CandlestickData} CandlestickData + * @typedef {_LineData} LineData + * @typedef {_BaselineData} 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 - */ - 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); }); diff --git a/websites/default/packages/solid-signals/wrapper.js b/websites/default/packages/solid-signals/wrapper.js index ad3a10f38..0c3ba827b 100644 --- a/websites/default/packages/solid-signals/wrapper.js +++ b/websites/default/packages/solid-signals/wrapper.js @@ -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 (_) {} } diff --git a/websites/default/scripts/main.js b/websites/default/scripts/main.js index a93f59dee..16472a4ff 100644 --- a/websites/default/scripts/main.js +++ b/websites/default/scripts/main.js @@ -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}>} */ ( 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>} */ 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(); diff --git a/websites/default/scripts/options.js b/websites/default/scripts/options.js index f3698a316..cb61ed037 100644 --- a/websites/default/scripts/options.js +++ b/websites/default/scripts/options.js @@ -1,16 +1,5 @@ // @ts-check -/** - * @typedef {Height | DateIndex | WeekIndex | MonthIndex | QuarterIndex | YearIndex | DecadeIndex} ChartableIndex - */ -/** - * @template {readonly unknown[]} T - * @typedef {Extract extends never ? false : true} IncludesChartableIndex - */ -/** - * @typedef {{[K in VecId]: IncludesChartableIndex 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} StartsWith + * @typedef {Extract} StartsWith */ /** * @template {string} S - * @typedef {Extract} EndsWith + * @typedef {Extract} 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