mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-26 07:39:59 -07:00
git: reset
This commit is contained in:
16
app/src/scripts/utils/array.ts
Normal file
16
app/src/scripts/utils/array.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export function sortedInsert(array: number[], value: number) {
|
||||
let low = 0;
|
||||
let high = array.length;
|
||||
|
||||
while (low < high) {
|
||||
const mid = (low + high) >>> 1;
|
||||
|
||||
if (array[mid] < value) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
|
||||
array.splice(low, 0, value);
|
||||
}
|
||||
246
app/src/scripts/utils/colors.ts
Normal file
246
app/src/scripts/utils/colors.ts
Normal file
@@ -0,0 +1,246 @@
|
||||
import {
|
||||
amber as amberTailwind,
|
||||
blue as blueTailwind,
|
||||
cyan as cyanTailwind,
|
||||
emerald as emeraldTailwind,
|
||||
fuchsia as fuchsiaTailwind,
|
||||
neutral as grayTailwind,
|
||||
green as greenTailwind,
|
||||
indigo as indigoTailwind,
|
||||
lime as limeTailwind,
|
||||
orange as orangeTailwind,
|
||||
pink as pinkTailwind,
|
||||
purple as purpleTailwind,
|
||||
red as redTailwind,
|
||||
rose as roseTailwind,
|
||||
sky as skyTailwind,
|
||||
teal as tealTailwind,
|
||||
violet as violetTailwind,
|
||||
yellow as yellowTailwind,
|
||||
} from "tailwindcss/colors";
|
||||
|
||||
// ---
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// DO NOT USE TRANSPARENCY HERE
|
||||
// ---
|
||||
|
||||
const lightRed = redTailwind[300];
|
||||
const red = redTailwind[500];
|
||||
const darkRed = redTailwind[900];
|
||||
const orange = orangeTailwind[500];
|
||||
const darkOrange = orangeTailwind[900];
|
||||
const amber = amberTailwind[500];
|
||||
const darkAmber = amberTailwind[900];
|
||||
const yellow = yellowTailwind[500];
|
||||
const darkYellow = yellowTailwind[500];
|
||||
const lime = limeTailwind[500];
|
||||
const darkLime = limeTailwind[900];
|
||||
const green = greenTailwind[500];
|
||||
const darkGreen = greenTailwind[900];
|
||||
const lightEmerald = emeraldTailwind[300];
|
||||
const emerald = emeraldTailwind[500];
|
||||
const darkEmerald = emeraldTailwind[900];
|
||||
const teal = tealTailwind[500];
|
||||
const darkTeal = tealTailwind[900];
|
||||
const cyan = cyanTailwind[500];
|
||||
const darkCyan = cyanTailwind[900];
|
||||
const sky = skyTailwind[500];
|
||||
const darkSky = skyTailwind[900];
|
||||
const blue = blueTailwind[500];
|
||||
const darkBlue = blueTailwind[900];
|
||||
const indigo = indigoTailwind[500];
|
||||
const darkIndigo = indigoTailwind[900];
|
||||
const violet = violetTailwind[500];
|
||||
const darkViolet = violetTailwind[900];
|
||||
const purple = purpleTailwind[500];
|
||||
const darkPurple = purpleTailwind[900];
|
||||
const fuchsia = fuchsiaTailwind[500];
|
||||
const darkFuchsia = fuchsiaTailwind[900];
|
||||
const pink = pinkTailwind[500];
|
||||
const darkPink = pinkTailwind[900];
|
||||
const rose = roseTailwind[500];
|
||||
const darkRose = roseTailwind[900];
|
||||
|
||||
const darkWhite = grayTailwind[400];
|
||||
const gray = grayTailwind[600];
|
||||
|
||||
const black = "#000000";
|
||||
const white = "#ffffff";
|
||||
|
||||
export const convertCandleToCandleColor = (
|
||||
candle: { close: number; open: number },
|
||||
inverse?: boolean,
|
||||
) =>
|
||||
(candle.close || 1) > (candle.open || 0)
|
||||
? !inverse
|
||||
? green
|
||||
: red
|
||||
: !inverse
|
||||
? red
|
||||
: green;
|
||||
|
||||
export const convertCandleToVolumeColor = (
|
||||
candle: { close: number; open: number },
|
||||
inverse?: boolean,
|
||||
) =>
|
||||
(candle.close || 1) > (candle.open || 0)
|
||||
? !inverse
|
||||
? darkGreen
|
||||
: darkRed
|
||||
: !inverse
|
||||
? darkRed
|
||||
: darkGreen;
|
||||
|
||||
export const colors = {
|
||||
white,
|
||||
darkWhite,
|
||||
gray,
|
||||
lightBitcoin: yellow,
|
||||
bitcoin: orange,
|
||||
darkBitcoin: darkOrange,
|
||||
lightDollars: lime,
|
||||
dollars: emerald,
|
||||
darkDollars: darkEmerald,
|
||||
|
||||
_1d: lightRed,
|
||||
_1w: red,
|
||||
_8d: orange,
|
||||
_13d: amber,
|
||||
_21d: yellow,
|
||||
_1m: lime,
|
||||
_34d: green,
|
||||
_55d: emerald,
|
||||
_89d: teal,
|
||||
_144d: cyan,
|
||||
_6m: sky,
|
||||
_1y: blue,
|
||||
_2y: indigo,
|
||||
_200w: violet,
|
||||
_4y: purple,
|
||||
_10y: fuchsia,
|
||||
|
||||
p2pk: lime,
|
||||
p2pkh: violet,
|
||||
p2sh: emerald,
|
||||
p2wpkh: cyan,
|
||||
p2wsh: pink,
|
||||
p2tr: blue,
|
||||
crab: red,
|
||||
fish: lime,
|
||||
humpback: violet,
|
||||
plankton: emerald,
|
||||
shark: cyan,
|
||||
shrimp: pink,
|
||||
whale: blue,
|
||||
megalodon: purple,
|
||||
realizedPrice: orange,
|
||||
oneMonthHolders: cyan,
|
||||
threeMonthsHolders: lime,
|
||||
sth: yellow,
|
||||
sixMonthsHolder: red,
|
||||
oneYearHolders: pink,
|
||||
twoYearsHolders: purple,
|
||||
lth: fuchsia,
|
||||
balancedPrice: yellow,
|
||||
cointimePrice: yellow,
|
||||
trueMarketMeanPrice: blue,
|
||||
vaultedPrice: green,
|
||||
cvdd: lime,
|
||||
terminalPrice: red,
|
||||
loss: red,
|
||||
darkLoss: darkRed,
|
||||
profit: green,
|
||||
darkProfit: darkGreen,
|
||||
thermoCap: green,
|
||||
investorCap: rose,
|
||||
realizedCap: orange,
|
||||
ethereum: indigo,
|
||||
usdt: emerald,
|
||||
usdc: blue,
|
||||
ust: red,
|
||||
busd: yellow,
|
||||
usdd: emerald,
|
||||
frax: gray,
|
||||
dai: amber,
|
||||
tusd: indigo,
|
||||
pyusd: blue,
|
||||
darkLiveliness: darkRose,
|
||||
liveliness: rose,
|
||||
vaultedness: green,
|
||||
activityToVaultednessRatio: violet,
|
||||
up_to_1d: lightRed,
|
||||
up_to_1w: red,
|
||||
up_to_1m: orange,
|
||||
up_to_2m: orange,
|
||||
up_to_3m: orange,
|
||||
up_to_4m: orange,
|
||||
up_to_5m: orange,
|
||||
up_to_6m: orange,
|
||||
up_to_1y: orange,
|
||||
up_to_2y: orange,
|
||||
up_to_3y: orange,
|
||||
up_to_4y: orange,
|
||||
up_to_5y: orange,
|
||||
up_to_7y: orange,
|
||||
up_to_10y: orange,
|
||||
up_to_15y: orange,
|
||||
from_10y_to_15y: purple,
|
||||
from_7y_to_10y: violet,
|
||||
from_5y_to_7y: indigo,
|
||||
from_3y_to_5y: sky,
|
||||
from_2y_to_3y: teal,
|
||||
from_1y_to_2y: green,
|
||||
from_6m_to_1y: lime,
|
||||
from_3m_to_6m: yellow,
|
||||
from_1m_to_3m: amber,
|
||||
from_1w_to_1m: orange,
|
||||
from_1d_to_1w: red,
|
||||
from_1y: green,
|
||||
from_2y: teal,
|
||||
from_4y: indigo,
|
||||
from_10y: violet,
|
||||
from_15y: fuchsia,
|
||||
coinblocksCreated: purple,
|
||||
coinblocksDestroyed: red,
|
||||
coinblocksStored: green,
|
||||
momentum: [green, yellow, red],
|
||||
momentumGreen: green,
|
||||
momentumYellow: yellow,
|
||||
momentumRed: red,
|
||||
extremeMax: red,
|
||||
extremeMiddle: orange,
|
||||
extremeMin: yellow,
|
||||
year_2009: yellow,
|
||||
year_2010: yellow,
|
||||
year_2011: yellow,
|
||||
year_2012: yellow,
|
||||
year_2013: yellow,
|
||||
year_2014: yellow,
|
||||
year_2015: yellow,
|
||||
year_2016: yellow,
|
||||
year_2017: yellow,
|
||||
year_2018: yellow,
|
||||
year_2019: yellow,
|
||||
year_2020: yellow,
|
||||
year_2021: yellow,
|
||||
year_2022: yellow,
|
||||
year_2023: yellow,
|
||||
year_2024: yellow,
|
||||
};
|
||||
10
app/src/scripts/utils/date.ts
Normal file
10
app/src/scripts/utils/date.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
// import { ONE_DAY_IN_MS } from "./time";
|
||||
|
||||
import { ONE_DAY_IN_MS } from "./time";
|
||||
|
||||
export const dateToString = (date: Date) => date.toJSON().split("T")[0];
|
||||
|
||||
// export const FIVE_MONTHS_IN_DAYS = 30 * 5;
|
||||
|
||||
export const getNumberOfDaysBetweenTwoDates = (oldest: Date, youngest: Date) =>
|
||||
Math.round(Math.abs((youngest.valueOf() - oldest.valueOf()) / ONE_DAY_IN_MS));
|
||||
19
app/src/scripts/utils/debounce.ts
Normal file
19
app/src/scripts/utils/debounce.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export const debounce = <F extends (...args: any[]) => any>(
|
||||
callback: F,
|
||||
wait = 250,
|
||||
) => {
|
||||
let timeoutId: number | undefined;
|
||||
let latestArgs: Parameters<F>;
|
||||
|
||||
return (...args: Parameters<F>) => {
|
||||
latestArgs = args;
|
||||
|
||||
if (!timeoutId) {
|
||||
timeoutId = window.setTimeout(async () => {
|
||||
await callback(...latestArgs);
|
||||
|
||||
timeoutId = undefined;
|
||||
}, wait);
|
||||
}
|
||||
};
|
||||
};
|
||||
12
app/src/scripts/utils/history.ts
Normal file
12
app/src/scripts/utils/history.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export function replaceHistory({
|
||||
urlParams,
|
||||
pathname,
|
||||
}: {
|
||||
urlParams?: URLSearchParams;
|
||||
pathname?: string;
|
||||
}) {
|
||||
urlParams ||= new URLSearchParams(window.location.search);
|
||||
pathname ||= window.location.pathname;
|
||||
|
||||
window.history.replaceState(null, "", `${pathname}?${urlParams.toString()}`);
|
||||
}
|
||||
3
app/src/scripts/utils/id.ts
Normal file
3
app/src/scripts/utils/id.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function stringToId(s: string) {
|
||||
return s.replace(/\W/g, " ").trim().replace(/ +/g, "-").toLowerCase();
|
||||
}
|
||||
31
app/src/scripts/utils/locale.ts
Normal file
31
app/src/scripts/utils/locale.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export const priceToUSLocale = (price: number, compact = true) => {
|
||||
const absolutePrice = Math.abs(price);
|
||||
const lessThan100 = absolutePrice < 100;
|
||||
const lessThan1000 = absolutePrice < 1_000;
|
||||
const biggerThanMillion = absolutePrice >= 1_000_000;
|
||||
|
||||
return numberToUSLocale(
|
||||
price,
|
||||
lessThan1000 ? (lessThan100 ? 2 : 1) : biggerThanMillion ? 3 : 0,
|
||||
biggerThanMillion && compact
|
||||
? {
|
||||
notation: "compact",
|
||||
compactDisplay: "short",
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
};
|
||||
|
||||
export const percentageToUSLocale = (percentage: number) =>
|
||||
numberToUSLocale(percentage, 1);
|
||||
|
||||
const numberToUSLocale = (
|
||||
value: number,
|
||||
digits: number,
|
||||
options?: Intl.NumberFormatOptions | undefined,
|
||||
) =>
|
||||
value.toLocaleString("en-us", {
|
||||
...options,
|
||||
minimumFractionDigits: digits,
|
||||
maximumFractionDigits: digits,
|
||||
});
|
||||
22
app/src/scripts/utils/math/averages.ts
Normal file
22
app/src/scripts/utils/math/averages.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { computeSum } from "./sum";
|
||||
|
||||
export const computeAverage = (values: number[]) =>
|
||||
computeSum(values) / values.length;
|
||||
|
||||
export const computeMovingAverage = <
|
||||
T extends SingleValueData = SingleValueData,
|
||||
>(
|
||||
dataset: T[],
|
||||
interval: number,
|
||||
) => {
|
||||
if (!dataset.length) return [];
|
||||
|
||||
return dataset.map((data, index) => ({
|
||||
...data,
|
||||
value: computeAverage(
|
||||
dataset
|
||||
.slice(Math.max(index - interval + 1, 0), index + 1)
|
||||
.map((data) => data.value || 1),
|
||||
),
|
||||
}));
|
||||
};
|
||||
5
app/src/scripts/utils/math/random.ts
Normal file
5
app/src/scripts/utils/math/random.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export function random<T>(array: T[]) {
|
||||
if (array && array.length) {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
}
|
||||
4
app/src/scripts/utils/math/round.ts
Normal file
4
app/src/scripts/utils/math/round.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const roundValue = (value: number, decimals = 5) => {
|
||||
const tenPowerX = 10 ** decimals;
|
||||
return Math.round(value * tenPowerX) / tenPowerX;
|
||||
};
|
||||
2
app/src/scripts/utils/math/sum.ts
Normal file
2
app/src/scripts/utils/math/sum.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const computeSum = (values: number[]) =>
|
||||
values.reduce((total, currentValue) => total + currentValue, 0);
|
||||
1
app/src/scripts/utils/run.ts
Normal file
1
app/src/scripts/utils/run.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const run = <T>(f: () => T) => f();
|
||||
9
app/src/scripts/utils/scroll.ts
Normal file
9
app/src/scripts/utils/scroll.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export const scrollIntoView = (
|
||||
element?: HTMLElement | Element | null,
|
||||
block: ScrollLogicalPosition = "nearest",
|
||||
behavior: ScrollBehavior = "instant",
|
||||
) =>
|
||||
element?.scrollIntoView({
|
||||
block,
|
||||
behavior,
|
||||
});
|
||||
119
app/src/scripts/utils/selectableList/index.ts
Normal file
119
app/src/scripts/utils/selectableList/index.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
export const createSelectableList = <T, L extends T[] = T[]>(
|
||||
list: L,
|
||||
parameters?: {
|
||||
selected?: L[number];
|
||||
selectedIndex?: number | null;
|
||||
},
|
||||
) => {
|
||||
const selected = createRWS<L[number] | null>(null);
|
||||
const selectedIndex = createRWS<number | null>(null);
|
||||
|
||||
const selectableList: SelectableList<L[number], L> = {
|
||||
selected,
|
||||
selectedIndex,
|
||||
list: createRWS(list, {
|
||||
equals: false,
|
||||
}),
|
||||
select(s) {
|
||||
if (this.selected() !== s) {
|
||||
batch(() => {
|
||||
selected.set(() => s);
|
||||
this.selectIndex(this.list().indexOf(s) ?? null);
|
||||
});
|
||||
}
|
||||
},
|
||||
resetSelected() {
|
||||
selected.set(null);
|
||||
selectedIndex.set(null);
|
||||
},
|
||||
selectFind(search, callback) {
|
||||
const element = this.list().find(
|
||||
(_element) => callback(_element) === search,
|
||||
);
|
||||
|
||||
if (element) {
|
||||
this.select(element);
|
||||
}
|
||||
|
||||
return element;
|
||||
},
|
||||
selectIndex(i) {
|
||||
i = i === -1 ? null : i;
|
||||
|
||||
if (i && (i < 0 || i >= this.list().length)) {
|
||||
throw new Error(
|
||||
`SelectableList: selectIndex: ${i} is incorrect ! (has ${
|
||||
this.list().length
|
||||
} elements)`,
|
||||
);
|
||||
}
|
||||
|
||||
if (i !== this.selectedIndex()) {
|
||||
selectedIndex.set(i);
|
||||
|
||||
const value = getValueFromIndexInList<L[number]>(i, this.list());
|
||||
|
||||
if (value !== null) {
|
||||
this.select(value);
|
||||
}
|
||||
}
|
||||
},
|
||||
push(value) {
|
||||
this.list.set((l) => {
|
||||
l.push(value);
|
||||
return l;
|
||||
});
|
||||
},
|
||||
pushAndSelect(value) {
|
||||
batch(() => {
|
||||
this.push(value);
|
||||
this.select(value);
|
||||
});
|
||||
},
|
||||
removeIndex(index) {
|
||||
let value = null;
|
||||
this.list.set((l) => {
|
||||
value = l.splice(index, 1)?.[0];
|
||||
return l;
|
||||
});
|
||||
return value;
|
||||
},
|
||||
toJSON<TJSON, LJSON extends TJSON[] = TJSON[]>(
|
||||
transform: (value: T) => TJSON,
|
||||
filter?: (value: T) => boolean,
|
||||
): JSONSelectableList<TJSON, LJSON> {
|
||||
return {
|
||||
version: 1,
|
||||
selectedIndex: getIndexOfSelectedInSelectableList(this),
|
||||
list: (filter ? this.list().filter(filter) : this.list()).map((value) =>
|
||||
transform(value),
|
||||
) as LJSON,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
if (parameters?.selected !== undefined) {
|
||||
selectableList.select(parameters.selected);
|
||||
} else if (parameters?.selectedIndex !== undefined) {
|
||||
selectableList.selectIndex(parameters.selectedIndex);
|
||||
}
|
||||
|
||||
return selectableList;
|
||||
};
|
||||
|
||||
export const createSL = createSelectableList;
|
||||
|
||||
export const getIndexOfSelectedInSelectableList = <T, L extends T[] = T[]>(
|
||||
sl: SelectableList<L[number], L>,
|
||||
) => {
|
||||
const selected = sl.selected();
|
||||
|
||||
return selected ? sl.list().indexOf(selected) : null;
|
||||
};
|
||||
|
||||
const getValueFromIndexInList = <T, L extends T[] = T[]>(
|
||||
index: number | null,
|
||||
list: L,
|
||||
) => (index !== null && list.length > 0 ? list.at(index) || list[0] : null);
|
||||
33
app/src/scripts/utils/selectableList/types.d.ts
vendored
Normal file
33
app/src/scripts/utils/selectableList/types.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// ---
|
||||
// JSON
|
||||
// ---
|
||||
|
||||
interface JSONSelectableList<T, L extends T[] = T[]> {
|
||||
readonly version: 1;
|
||||
selectedIndex: number | null;
|
||||
readonly list: L;
|
||||
}
|
||||
|
||||
// ---
|
||||
// Object
|
||||
// ---
|
||||
|
||||
interface SelectableList<T, L extends T[] = T[]> {
|
||||
readonly selected: Accessor<T | null>;
|
||||
readonly selectedIndex: Accessor<number | null>;
|
||||
readonly list: RWS<L>;
|
||||
readonly select: <S extends L[number] = L[number]>(s: S) => void;
|
||||
readonly selectFind: <K>(
|
||||
search: K,
|
||||
callback: (element: T) => K,
|
||||
) => T | undefined;
|
||||
readonly selectIndex: (i: number | null) => void;
|
||||
readonly push: <S extends L[number] = L[number]>(s: S) => void;
|
||||
readonly pushAndSelect: <S extends L[number] = L[number]>(s: S) => void;
|
||||
readonly removeIndex: (i: number) => L[number] | null;
|
||||
readonly resetSelected: VoidFunction;
|
||||
readonly toJSON: <TJSON, LJSON extends TJSON[] = TJSON[]>(
|
||||
transform: (value: T) => LJSON[number],
|
||||
filter?: (value: T) => boolean,
|
||||
) => JSONSelectableList<TJSON, LJSON>;
|
||||
}
|
||||
9
app/src/scripts/utils/sleep.ts
Normal file
9
app/src/scripts/utils/sleep.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export function sleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
export function tick() {
|
||||
return sleep(1);
|
||||
}
|
||||
19
app/src/scripts/utils/storage.ts
Normal file
19
app/src/scripts/utils/storage.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export function saveToStorage(key?: string, value?: string | boolean) {
|
||||
if (key) {
|
||||
value !== undefined && value !== null
|
||||
? localStorage.setItem(key, String(value))
|
||||
: localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
export function readBooleanFromStorage(key: string) {
|
||||
const saved = localStorage.getItem(key);
|
||||
if (saved) {
|
||||
return isSerializedBooleanTrue(saved);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isSerializedBooleanTrue(serialized: string) {
|
||||
return serialized === "true" || serialized === "1";
|
||||
}
|
||||
8
app/src/scripts/utils/time.ts
Normal file
8
app/src/scripts/utils/time.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const ONE_SECOND_IN_MS = 1_000;
|
||||
export const FIVE_SECOND_IN_MS = 5 * ONE_SECOND_IN_MS;
|
||||
export const TEN_SECOND_IN_MS = 2 * FIVE_SECOND_IN_MS;
|
||||
export const ONE_MINUTE_IN_MS = 6 * TEN_SECOND_IN_MS;
|
||||
export const FIVE_MINUTES_IN_MS = 5 * ONE_MINUTE_IN_MS;
|
||||
export const TEN_MINUTES_IN_MS = 2 * FIVE_MINUTES_IN_MS;
|
||||
export const ONE_HOUR_IN_MS = 6 * TEN_MINUTES_IN_MS;
|
||||
export const ONE_DAY_IN_MS = 24 * ONE_HOUR_IN_MS;
|
||||
40
app/src/scripts/utils/urlParams.ts
Normal file
40
app/src/scripts/utils/urlParams.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { replaceHistory } from "./history";
|
||||
import { isSerializedBooleanTrue } from "./storage";
|
||||
|
||||
const whitelist = ["from", "to"];
|
||||
|
||||
export function resetURLParams() {
|
||||
const urlParams = new URLSearchParams();
|
||||
|
||||
[...new URLSearchParams(window.location.search).entries()]
|
||||
.filter(([key, _]) => whitelist.includes(key))
|
||||
.forEach(([key, value]) => {
|
||||
urlParams.set(key, value);
|
||||
});
|
||||
|
||||
replaceHistory({ urlParams });
|
||||
}
|
||||
|
||||
export function writeURLParam(key: string, value?: string | boolean) {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
if (value !== undefined) {
|
||||
urlParams.set(key, String(value));
|
||||
} else {
|
||||
urlParams.delete(key);
|
||||
}
|
||||
|
||||
replaceHistory({ urlParams });
|
||||
}
|
||||
|
||||
export function readBooleanURLParam(key: string) {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
const parameter = urlParams.get(key);
|
||||
|
||||
if (parameter) {
|
||||
return isSerializedBooleanTrue(parameter);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user