From d06784958d73159b5e4abafe5114804662114ed7 Mon Sep 17 00:00:00 2001 From: Ryan Schanzenbacher Date: Thu, 9 Jul 2026 22:15:53 -0400 Subject: move ubersicht modules in tree --- .../lib/components/data/crypto.jsx | 160 +++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100755 users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx (limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx') diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx new file mode 100755 index 0000000..3faf4ea --- /dev/null +++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx @@ -0,0 +1,160 @@ +import * as Uebersicht from "uebersicht"; +import * as DataWidget from "./data-widget.jsx"; +import * as DataWidgetLoader from "./data-widget-loader.jsx"; +import * as Icons from "../icons/icons.jsx"; +import useWidgetRefresh from "../../hooks/use-widget-refresh"; +import useServerSocket from "../../hooks/use-server-socket"; +import { useSimpleBarContext } from "../simple-bar-context.jsx"; +import * as Utils from "../../utils"; + +export { cryptoStyles as styles } from "../../styles/components/data/crypto"; + +const { React } = Uebersicht; + +const DEFAULT_REFRESH_FREQUENCY = 5 * 60 * 1000; // Default refresh frequency set to 5 minutes + +/** + * Crypto Widget Component + * @returns {JSX.Element|null} The Crypto Widget component + */ +export const Widget = React.memo(() => { + const { displayIndex, settings, pushMissive } = useSimpleBarContext(); + const { widgets, cryptoWidgetOptions } = settings; + const { cryptoWidget } = widgets; + const { + refreshFrequency, + denomination, + identifiers, + precision, + showOnDisplay, + showIcon, + } = cryptoWidgetOptions; + + // Calculate the refresh frequency using the provided or default value + const refresh = React.useMemo( + () => + Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY), + [refreshFrequency], + ); + + // Determine if the widget should be visible on the current display + const visible = + Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && cryptoWidget; + + const ref = React.useRef(); + const denominatorToken = getDenominatorToken(denomination); + + // Memoize cleanedUpIdentifiers to prevent recreation on every render + const cleanedUpIdentifiers = React.useMemo( + () => identifiers.replace(/ /g, ""), + [identifiers], + ); + + // Memoize enumeratedIdentifiers to prevent recreation on every render + const enumeratedIdentifiers = React.useMemo( + () => cleanedUpIdentifiers.replace(/ /g, "").split(","), + [cleanedUpIdentifiers], + ); + + const [state, setState] = React.useState(); + const [loading, setLoading] = React.useState(visible); + + // Reset the widget state + const resetWidget = () => { + setState(undefined); + setLoading(false); + }; + + /** + * Fetches cryptocurrency prices from the CoinGecko API + */ + const getCrypto = React.useCallback(async () => { + if (!visible) return; + const response = await fetch( + `https://api.coingecko.com/api/v3/simple/price?ids=${cleanedUpIdentifiers}&vs_currencies=${denomination}`, + ); + const result = await response.json(); + + const prices = enumeratedIdentifiers.map((id) => { + const value = parseFloat(result[id][denomination]).toFixed(precision); + return `${denominatorToken}${value}`; + }); + setState(prices); + setLoading(false); + }, [ + visible, + cleanedUpIdentifiers, + denomination, + enumeratedIdentifiers, + precision, + denominatorToken, + ]); + + useServerSocket("crypto", visible, getCrypto, resetWidget, setLoading); + useWidgetRefresh(visible, getCrypto, refresh); + + /** + * Refreshes the cryptocurrency prices + * @param {Event} e - The event object + */ + const refreshCrypto = (e) => { + Utils.clickEffect(e); + setLoading(true); + getCrypto(); + Utils.notification("Refreshing price from coingecko.com...", pushMissive); + }; + + if (loading) return ; + if (!state) return null; + + const classes = Utils.classNames("crypto"); + + return enumeratedIdentifiers.map((id, i) => ( + openCrypto(e, pushMissive)} + onRightClick={refreshCrypto} + > + {state[i]} + + )); +}); + +Widget.displayName = "Crypto"; + +/** + * Returns the icon component for a given cryptocurrency identifier + * @param {string} identifier - The cryptocurrency identifier + * @returns {JSX.Element} The icon component + */ +function getIcon(identifier) { + if (identifier === "celo") return Icons.Celo; + if (identifier === "ethereum") return Icons.Ethereum; + if (identifier === "bitcoin") return Icons.Bitcoin; + return Icons.Moon; +} + +/** + * Returns the symbol for a given denomination + * @param {string} denomination - The denomination (e.g., "usd", "eur") + * @returns {string} The symbol for the denomination + */ +function getDenominatorToken(denomination) { + if (denomination === "usd") return "$"; + if (denomination === "eur") return "€"; + return ""; +} + +/** + * Opens the cryptocurrency price chart + * @param {Event} e - The event object + * @param {Function} pushMissive - The function to push a notification + */ +function openCrypto(e, pushMissive) { + Utils.clickEffect(e); + Utils.notification("Opening price chart from coingecko.com...", pushMissive); +} -- cgit v1.3