diff --git a/package-lock.json b/package-lock.json
index d4c1c1a7..157e7239 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -53,6 +53,7 @@
"svelte-range-slider-pips": "^2.3.1",
"svelte-sonner": "^0.3.27",
"svelte-tags-input": "^6.0.0",
+ "svelte-tiny-virtual-list": "^2.1.2",
"tailwind-merge": "^2.4.0",
"tailwind-variants": "^0.2.1",
"tslib": "^2.6.2",
@@ -7640,6 +7641,11 @@
"resolved": "https://registry.npmjs.org/svelte-tags-input/-/svelte-tags-input-6.0.1.tgz",
"integrity": "sha512-3X5qomFSXe6E8H7Lq0oce7096tr6u06pWvTNgNoeNVIXCrRLxRYOk4Ujkte7z5WaAit47EUsZZP1TSJ2HR9ixA=="
},
+ "node_modules/svelte-tiny-virtual-list": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/svelte-tiny-virtual-list/-/svelte-tiny-virtual-list-2.1.2.tgz",
+ "integrity": "sha512-jeP/WMvgFUR4mYXHGPiCexjX5DuzSO+3xzHNhxfcsFyy+uYPtnqI5UGb383swpzQAyXB0OBqYfzpYihD/5gxnA=="
+ },
"node_modules/svelte-writable-derived": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/svelte-writable-derived/-/svelte-writable-derived-3.1.1.tgz",
diff --git a/package.json b/package.json
index 38f085e0..81922428 100644
--- a/package.json
+++ b/package.json
@@ -95,6 +95,7 @@
"svelte-range-slider-pips": "^2.3.1",
"svelte-sonner": "^0.3.27",
"svelte-tags-input": "^6.0.0",
+ "svelte-tiny-virtual-list": "^2.1.2",
"tailwind-merge": "^2.4.0",
"tailwind-variants": "^0.2.1",
"tslib": "^2.6.2",
diff --git a/src/routes/options-flow/+page.svelte b/src/routes/options-flow/+page.svelte
index cbb7a8ac..6213c373 100644
--- a/src/routes/options-flow/+page.svelte
+++ b/src/routes/options-flow/+page.svelte
@@ -6,7 +6,7 @@
import { abbreviateNumber } from '$lib/utils';
import { onMount, onDestroy } from 'svelte';
import toast from 'svelte-french-toast';
-
+ import VirtualList from 'svelte-tiny-virtual-list';
export let data;
@@ -22,7 +22,6 @@
}
});
- let optionList = []
let rawData = [];
let filterList = [];
@@ -159,11 +158,9 @@ function handleViewData(optionData) {
rawData = listFilteredData;
}
- // Update optionList and notFound status
if (rawData?.length !== 0 && newIncomingData === true) {
notFound = false;
newIncomingData = false;
- optionList = rawData?.slice(0, 50);
} else if (!newIncomingData) {
notFound = false;
newIncomingData = false;
@@ -171,7 +168,6 @@ function handleViewData(optionData) {
notFound = true;
newIncomingData = false;
rawData = data?.getOptionsFlowFeed ?? [];
- optionList = [];
}
calculateStats(rawData);
@@ -206,7 +202,6 @@ function handleViewData(optionData) {
onMount(async () => {
audio = new Audio(notifySound);
rawData = data?.getOptionsFlowFeed;
- optionList = rawData?.slice(0, 100);
calculateStats(rawData);
isLoaded = true;
@@ -214,32 +209,11 @@ function handleViewData(optionData) {
await websocketRealtimeData();
}
- if (data?.user?.tier === 'Pro') {
- const attachScrollListener = () => {
- if (scrollContainer) {
- scrollContainer.addEventListener('scroll', handleScroll);
- return true;
- }
- return false;
- };
- if (!attachScrollListener()) {
- const observer = new MutationObserver(() => {
- if (attachScrollListener()) {
- observer.disconnect();
- }
- });
-
- observer.observe(document.body, { childList: true, subtree: true });
- }
- }
});
onDestroy(async() => {
- if (scrollContainer && data?.user?.tier === 'Pro') {
- scrollContainer.removeEventListener('scroll', handleScroll);
- };
if (typeof window !== 'undefined')
{
@@ -252,18 +226,7 @@ onDestroy(async() => {
})
- async function handleScroll() {
- if (!scrollContainer) return;
- const scrollThreshold = scrollContainer.scrollHeight * 0.8; // 80% of the div height
- const isBottom = scrollContainer.scrollTop + scrollContainer.clientHeight >= scrollThreshold;
- if (isBottom && optionList?.length !== rawData?.length) {
- const nextIndex = optionList?.length;
- const filteredNewResults = rawData?.slice(nextIndex, nextIndex + 25);
- optionList = [...optionList, ...filteredNewResults];
- }
- }
-
async function assetSelector(symbol, assetType)
{
@@ -287,8 +250,8 @@ onDestroy(async() => {
-function calculateStats(optionList) {
- const { callVolumeSum, putVolumeSum, bullishCount, bearishCount } = optionList?.reduce((acc, item) => {
+function calculateStats(data) {
+ const { callVolumeSum, putVolumeSum, bullishCount, bearishCount } = data?.reduce((acc, item) => {
const volume = parseInt(item?.volume);
if (item?.put_call === "Calls") {
@@ -414,19 +377,15 @@ function handleInput(event) {
if (newData?.length !== 0) {
rawData = newData;
- optionList = [...rawData?.slice(0, 100)];
-
notFound = false;
} else {
notFound = true;
rawData = data?.getOptionsFlowFeed;
- optionList = rawData?.slice(0, 100);
}
} else {
notFound = false;
rawData = data?.getOptionsFlowFeed;
- optionList = rawData?.slice(0, 100);
}
calculateStats(rawData);
@@ -487,24 +446,23 @@ $: {
const newData = filterExpiringSoon(rawData, Math.max(...filterList));
if (newData?.length !== 0) {
rawData = newData;
- optionList = rawData?.slice(0, 50);
notFound = false;
} else {
notFound = true;
rawData = data?.getOptionsFlowFeed;
- optionList = [];
}
}
else if (filterQuery?.length === 0) {
rawData = data?.getOptionsFlowFeed;
- optionList = rawData?.slice(0,100);
}
calculateStats(rawData);
}
}
+
+
| Time | -Symbol | -Expiry | -Strike | -C/P | -Sent. | -Spot | -Price | -Prem. | -Type | -Vol | -OI | -|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| - {formatTime(item?.time)} - | - -assetSelector(item?.ticker, item?.assetType)} class="{index % 2 ? 'bg-[#09090B]' : 'bg-[#27272A]'} text-blue-400 text-start font-normal"> - {item?.ticker} - | - -- {reformatDate(item?.date_expiration)} - | - -- {item?.strike_price} - | - -- {item?.put_call} - | - -- {item?.sentiment} - | - -- {item?.underlying_price} - | - -- {item?.price} - | - -- {abbreviateNumber(item?.cost_basis)} - | - -- {item?.type} - | - - - -- {new Intl.NumberFormat("en", { - minimumFractionDigits: 0, - maximumFractionDigits: 0 - }).format(item?.volume)} - | - -- {new Intl.NumberFormat("en", { - minimumFractionDigits: 0, - maximumFractionDigits: 0 - }).format(item?.open_interest)} - | - +Symbol | +