aboutsummaryrefslogtreecommitdiff
path: root/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx')
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx160
1 files changed, 160 insertions, 0 deletions
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 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { cryptoStyles as styles } from "../../styles/components/data/crypto";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 5 * 60 * 1000; // Default refresh frequency set to 5 minutes
15
16/**
17 * Crypto Widget Component
18 * @returns {JSX.Element|null} The Crypto Widget component
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
22 const { widgets, cryptoWidgetOptions } = settings;
23 const { cryptoWidget } = widgets;
24 const {
25 refreshFrequency,
26 denomination,
27 identifiers,
28 precision,
29 showOnDisplay,
30 showIcon,
31 } = cryptoWidgetOptions;
32
33 // Calculate the refresh frequency using the provided or default value
34 const refresh = React.useMemo(
35 () =>
36 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
37 [refreshFrequency],
38 );
39
40 // Determine if the widget should be visible on the current display
41 const visible =
42 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && cryptoWidget;
43
44 const ref = React.useRef();
45 const denominatorToken = getDenominatorToken(denomination);
46
47 // Memoize cleanedUpIdentifiers to prevent recreation on every render
48 const cleanedUpIdentifiers = React.useMemo(
49 () => identifiers.replace(/ /g, ""),
50 [identifiers],
51 );
52
53 // Memoize enumeratedIdentifiers to prevent recreation on every render
54 const enumeratedIdentifiers = React.useMemo(
55 () => cleanedUpIdentifiers.replace(/ /g, "").split(","),
56 [cleanedUpIdentifiers],
57 );
58
59 const [state, setState] = React.useState();
60 const [loading, setLoading] = React.useState(visible);
61
62 // Reset the widget state
63 const resetWidget = () => {
64 setState(undefined);
65 setLoading(false);
66 };
67
68 /**
69 * Fetches cryptocurrency prices from the CoinGecko API
70 */
71 const getCrypto = React.useCallback(async () => {
72 if (!visible) return;
73 const response = await fetch(
74 `https://api.coingecko.com/api/v3/simple/price?ids=${cleanedUpIdentifiers}&vs_currencies=${denomination}`,
75 );
76 const result = await response.json();
77
78 const prices = enumeratedIdentifiers.map((id) => {
79 const value = parseFloat(result[id][denomination]).toFixed(precision);
80 return `${denominatorToken}${value}`;
81 });
82 setState(prices);
83 setLoading(false);
84 }, [
85 visible,
86 cleanedUpIdentifiers,
87 denomination,
88 enumeratedIdentifiers,
89 precision,
90 denominatorToken,
91 ]);
92
93 useServerSocket("crypto", visible, getCrypto, resetWidget, setLoading);
94 useWidgetRefresh(visible, getCrypto, refresh);
95
96 /**
97 * Refreshes the cryptocurrency prices
98 * @param {Event} e - The event object
99 */
100 const refreshCrypto = (e) => {
101 Utils.clickEffect(e);
102 setLoading(true);
103 getCrypto();
104 Utils.notification("Refreshing price from coingecko.com...", pushMissive);
105 };
106
107 if (loading) return <DataWidgetLoader.Widget className="crypto" />;
108 if (!state) return null;
109
110 const classes = Utils.classNames("crypto");
111
112 return enumeratedIdentifiers.map((id, i) => (
113 <DataWidget.Widget
114 key={id}
115 classes={classes}
116 ref={ref}
117 Icon={showIcon ? getIcon(id) : null}
118 href={`https://coingecko.com/en/coins/${id}`}
119 onClick={(e) => openCrypto(e, pushMissive)}
120 onRightClick={refreshCrypto}
121 >
122 {state[i]}
123 </DataWidget.Widget>
124 ));
125});
126
127Widget.displayName = "Crypto";
128
129/**
130 * Returns the icon component for a given cryptocurrency identifier
131 * @param {string} identifier - The cryptocurrency identifier
132 * @returns {JSX.Element} The icon component
133 */
134function getIcon(identifier) {
135 if (identifier === "celo") return Icons.Celo;
136 if (identifier === "ethereum") return Icons.Ethereum;
137 if (identifier === "bitcoin") return Icons.Bitcoin;
138 return Icons.Moon;
139}
140
141/**
142 * Returns the symbol for a given denomination
143 * @param {string} denomination - The denomination (e.g., "usd", "eur")
144 * @returns {string} The symbol for the denomination
145 */
146function getDenominatorToken(denomination) {
147 if (denomination === "usd") return "$";
148 if (denomination === "eur") return "€";
149 return "";
150}
151
152/**
153 * Opens the cryptocurrency price chart
154 * @param {Event} e - The event object
155 * @param {Function} pushMissive - The function to push a notification
156 */
157function openCrypto(e, pushMissive) {
158 Utils.clickEffect(e);
159 Utils.notification("Opening price chart from coingecko.com...", pushMissive);
160}