@@ -22,6 +22,169 @@ const CATEGORY_ICONS = {
2222 stocks : "📈" ,
2323} ;
2424
25+ const CURRENCY_SYMBOLS = {
26+ AED : "د.إ" ,
27+ AFN : "؋" ,
28+ ALL : "L" ,
29+ AMD : "֏" ,
30+ ANG : "ƒ" ,
31+ AOA : "Kz" ,
32+ ARS : "$" ,
33+ AUD : "$" ,
34+ AWG : "ƒ" ,
35+ AZN : "₼" ,
36+ BAM : "KM" ,
37+ BBD : "$" ,
38+ BDT : "৳" ,
39+ BGN : "лв" ,
40+ BHD : ".د.ب" ,
41+ BIF : "FBu" ,
42+ BMD : "$" ,
43+ BND : "$" ,
44+ BOB : "$b" ,
45+ BRL : "R$" ,
46+ BSD : "$" ,
47+ BTN : "Nu." ,
48+ BWP : "P" ,
49+ BYN : "Br" ,
50+ BZD : "BZ$" ,
51+ CAD : "$" ,
52+ CDF : "FC" ,
53+ CHF : "CHF" ,
54+ CLP : "$" ,
55+ CNY : "¥" ,
56+ COP : "$" ,
57+ CRC : "₡" ,
58+ CUC : "$" ,
59+ CUP : "₱" ,
60+ CVE : "$" ,
61+ CZK : "Kč" ,
62+ DJF : "Fdj" ,
63+ DKK : "kr" ,
64+ DOP : "RD$" ,
65+ DZD : "دج" ,
66+ EGP : "£" ,
67+ ERN : "Nfk" ,
68+ ETB : "Br" ,
69+ EUR : "€" ,
70+ FJD : "$" ,
71+ FKP : "£" ,
72+ GBP : "£" ,
73+ GEL : "₾" ,
74+ GGP : "£" ,
75+ GHS : "GH₵" ,
76+ GIP : "£" ,
77+ GMD : "D" ,
78+ GNF : "FG" ,
79+ GTQ : "Q" ,
80+ GYD : "$" ,
81+ HKD : "$" ,
82+ HNL : "L" ,
83+ HRK : "kn" ,
84+ HTG : "G" ,
85+ HUF : "Ft" ,
86+ IDR : "Rp" ,
87+ ILS : "₪" ,
88+ IMP : "£" ,
89+ INR : "₹" ,
90+ IQD : "ع.د" ,
91+ IRR : "﷼" ,
92+ ISK : "kr" ,
93+ JEP : "£" ,
94+ JMD : "J$" ,
95+ JOD : "JD" ,
96+ JPY : "¥" ,
97+ KES : "KSh" ,
98+ KGS : "лв" ,
99+ KHR : "៛" ,
100+ KMF : "CF" ,
101+ KPW : "₩" ,
102+ KRW : "₩" ,
103+ KWD : "KD" ,
104+ KYD : "$" ,
105+ KZT : "₸" ,
106+ LAK : "₭" ,
107+ LBP : "£" ,
108+ LKR : "₨" ,
109+ LRD : "$" ,
110+ LSL : "M" ,
111+ LYD : "LD" ,
112+ MAD : "MAD" ,
113+ MDL : "lei" ,
114+ MGA : "Ar" ,
115+ MKD : "ден" ,
116+ MMK : "K" ,
117+ MNT : "₮" ,
118+ MOP : "MOP$" ,
119+ MRU : "UM" ,
120+ MUR : "₨" ,
121+ MVR : "Rf" ,
122+ MWK : "MK" ,
123+ MXN : "$" ,
124+ MYR : "RM" ,
125+ MZN : "MT" ,
126+ NAD : "$" ,
127+ NGN : "₦" ,
128+ NIO : "C$" ,
129+ NOK : "kr" ,
130+ NPR : "₨" ,
131+ NZD : "$" ,
132+ OMR : "﷼" ,
133+ PAB : "B/." ,
134+ PEN : "S/." ,
135+ PGK : "K" ,
136+ PHP : "₱" ,
137+ PKR : "₨" ,
138+ PLN : "zł" ,
139+ PYG : "Gs" ,
140+ QAR : "﷼" ,
141+ RON : "lei" ,
142+ RSD : "Дин." ,
143+ RUB : "₽" ,
144+ RWF : "R₣" ,
145+ SAR : "﷼" ,
146+ SBD : "$" ,
147+ SCR : "₨" ,
148+ SDG : "ج.س." ,
149+ SEK : "kr" ,
150+ SGD : "S$" ,
151+ SHP : "£" ,
152+ SLL : "Le" ,
153+ SOS : "S" ,
154+ SRD : "$" ,
155+ STN : "Db" ,
156+ SVC : "$" ,
157+ SYP : "£" ,
158+ SZL : "E" ,
159+ THB : "฿" ,
160+ TJS : "SM" ,
161+ TMT : "T" ,
162+ TND : "د.ت" ,
163+ TOP : "T$" ,
164+ TRY : "₺" ,
165+ TTD : "TT$" ,
166+ TWD : "NT$" ,
167+ TZS : "TSh" ,
168+ UAH : "₴" ,
169+ UGX : "USh" ,
170+ USD : "$" ,
171+ UYU : "$U" ,
172+ UZS : "лв" ,
173+ VEF : "Bs" ,
174+ VES : "Bs.S" ,
175+ VND : "₫" ,
176+ VUV : "VT" ,
177+ WST : "WS$" ,
178+ XAF : "FCFA" ,
179+ XCD : "$" ,
180+ XOF : "CFA" ,
181+ XPF : "₣" ,
182+ YER : "﷼" ,
183+ ZAR : "R" ,
184+ ZMW : "ZK" ,
185+ ZWL : "$" ,
186+ } ;
187+
25188const RabbitForexIndicator = GObject . registerClass (
26189 class RabbitForexIndicator extends PanelMenu . Button {
27190 _init ( extension ) {
@@ -82,6 +245,12 @@ const RabbitForexIndicator = GObject.registerClass(
82245 return this . _settings . get_strv ( `panel-${ category } ` ) ?? [ ] ;
83246 }
84247
248+ _getCurrencySymbol ( currency ) {
249+ const useCurrencySymbols = this . _settings . get_boolean ( "use-currency-symbols" ) ;
250+ if ( ! useCurrencySymbols ) return currency ;
251+ return CURRENCY_SYMBOLS [ currency ] || currency ;
252+ }
253+
85254 _buildMenu ( ) {
86255 // Rates section - will be populated dynamically
87256 this . _ratesSection = new PopupMenu . PopupMenuSection ( ) ;
@@ -252,15 +421,16 @@ const RabbitForexIndicator = GObject.registerClass(
252421 for ( const symbol of watched ) {
253422 if ( this . _rates [ category ] [ symbol ] !== undefined ) {
254423 const rate = this . _rates [ category ] [ symbol ] ;
424+ const rawPrice = this . _getRawPrice ( rate , category ) ;
255425 const displayRate = this . _formatDisplayRate ( rate , category , symbol , primaryCurrency ) ;
256426
257427 const rateItem = new PopupMenu . PopupMenuItem ( ` ${ symbol } : ${ displayRate } ` , { reactive : true } ) ;
258428
259- // Copy to clipboard on click
260429 rateItem . connect ( "activate" , ( ) => {
430+ const clipboardText = this . _getClipboardText ( symbol , rawPrice , displayRate , primaryCurrency , category ) ;
261431 const clipboard = St . Clipboard . get_default ( ) ;
262- clipboard . set_text ( St . ClipboardType . CLIPBOARD , ` ${ symbol } : ${ displayRate } ` ) ;
263- Main . notify ( "Copied to clipboard" , ` ${ symbol } : ${ displayRate } ` ) ;
432+ clipboard . set_text ( St . ClipboardType . CLIPBOARD , clipboardText ) ;
433+ Main . notify ( "Copied to clipboard" , clipboardText ) ;
264434 } ) ;
265435
266436 this . _ratesSection . addMenuItem ( rateItem ) ;
@@ -282,6 +452,37 @@ const RabbitForexIndicator = GObject.registerClass(
282452 }
283453 }
284454
455+ _getRawPrice ( rate , category ) {
456+ if ( category === "metals" ) {
457+ let price = 1 / rate ;
458+ const metalsUnit = this . _settings . get_string ( "metals-unit" ) ;
459+ if ( metalsUnit === "troy-ounce" ) {
460+ price = price * TROY_OUNCE_TO_GRAM ;
461+ }
462+ return price ;
463+ }
464+
465+ if ( category === "stocks" || category === "crypto" || category === "fiat" ) {
466+ return 1 / rate ;
467+ }
468+
469+ return rate ;
470+ }
471+
472+ _getClipboardText ( symbol , rawPrice , displayRate , primaryCurrency , category ) {
473+ const clipboardFormat = this . _settings . get_string ( "clipboard-format" ) ;
474+
475+ switch ( clipboardFormat ) {
476+ case "price-only" :
477+ return rawPrice . toString ( ) ;
478+ case "formatted-price" :
479+ return this . _formatNumber ( rawPrice ) ;
480+ case "display-format" :
481+ default :
482+ return `${ symbol } : ${ displayRate } ` ;
483+ }
484+ }
485+
285486 _formatPanelRate ( rate , category , symbol ) {
286487 if ( category === "metals" ) {
287488 let price = 1 / rate ;
@@ -306,47 +507,95 @@ const RabbitForexIndicator = GObject.registerClass(
306507 }
307508
308509 _formatDisplayRate ( rate , category , symbol , primaryCurrency ) {
510+ const currencySymbol = this . _getCurrencySymbol ( primaryCurrency ) ;
511+ const symbolPosition = this . _settings . get_string ( "symbol-position" ) ;
512+
309513 if ( category === "metals" ) {
310514 let price = 1 / rate ;
311515 const metalsUnit = this . _settings . get_string ( "metals-unit" ) ;
312516 if ( metalsUnit === "troy-ounce" ) {
313517 price = price * TROY_OUNCE_TO_GRAM ;
314518 }
315- return ` ${ this . _formatNumber ( price ) } ${ primaryCurrency } ` ;
519+ return this . _formatWithCurrency ( price , currencySymbol , primaryCurrency , symbolPosition ) ;
316520 }
317521
318522 if ( category === "stocks" ) {
319523 const price = 1 / rate ;
320- return ` ${ this . _formatNumber ( price ) } ${ primaryCurrency } ` ;
524+ return this . _formatWithCurrency ( price , currencySymbol , primaryCurrency , symbolPosition ) ;
321525 }
322526
323527 if ( category === "fiat" ) {
324528 const price = 1 / rate ;
325- return ` ${ this . _formatNumber ( price ) } ${ primaryCurrency } ` ;
529+ return this . _formatWithCurrency ( price , currencySymbol , primaryCurrency , symbolPosition ) ;
326530 }
327531
328532 if ( category === "crypto" ) {
329533 const price = 1 / rate ;
330- return ` ${ this . _formatNumber ( price ) } ${ primaryCurrency } ` ;
534+ return this . _formatWithCurrency ( price , currencySymbol , primaryCurrency , symbolPosition ) ;
331535 }
332536
333537 return this . _formatNumber ( rate ) ;
334538 }
335539
336- _formatNumber ( num ) {
337- if ( num >= 1000000 ) {
338- return ( num / 1000000 ) . toFixed ( 2 ) + "M" ;
339- } else if ( num >= 1 ) {
340- return num . toLocaleString ( "en-US" , { maximumFractionDigits : 2 } ) ;
341- } else if ( num >= 0.01 ) {
342- return num . toFixed ( 4 ) ;
343- } else if ( num >= 0.0001 ) {
344- return num . toFixed ( 6 ) ;
540+ _formatWithCurrency ( price , currencySymbol , primaryCurrency , position ) {
541+ const formattedPrice = this . _formatNumber ( price ) ;
542+ const useCurrencySymbols = this . _settings . get_boolean ( "use-currency-symbols" ) ;
543+
544+ if ( ! useCurrencySymbols ) {
545+ return `${ formattedPrice } ${ primaryCurrency } ` ;
546+ }
547+
548+ const isSymbol = CURRENCY_SYMBOLS [ primaryCurrency ] && CURRENCY_SYMBOLS [ primaryCurrency ] !== primaryCurrency ;
549+
550+ if ( ! isSymbol ) {
551+ return `${ formattedPrice } ${ primaryCurrency } ` ;
552+ }
553+
554+ if ( position === "before" ) {
555+ return `${ currencySymbol } ${ formattedPrice } ` ;
345556 } else {
346- return num . toExponential ( 4 ) ;
557+ return ` ${ formattedPrice } ${ currencySymbol } ` ;
347558 }
348559 }
349560
561+ _formatNumber ( num ) {
562+ const formatStyle = this . _settings . get_string ( "number-format" ) ;
563+ const decimalPlaces = this . _settings . get_int ( "decimal-places" ) ;
564+
565+ if ( formatStyle === "auto" ) {
566+ if ( num >= 1000000 ) {
567+ return ( num / 1000000 ) . toFixed ( 2 ) + "M" ;
568+ } else if ( num >= 1 ) {
569+ return num . toLocaleString ( "en-US" , { maximumFractionDigits : decimalPlaces } ) ;
570+ } else if ( num >= 0.01 ) {
571+ return num . toFixed ( Math . max ( decimalPlaces , 4 ) ) ;
572+ } else if ( num >= 0.0001 ) {
573+ return num . toFixed ( Math . max ( decimalPlaces , 6 ) ) ;
574+ } else {
575+ return num . toExponential ( 4 ) ;
576+ }
577+ } else if ( formatStyle === "fixed" ) {
578+ return num . toFixed ( decimalPlaces ) ;
579+ } else if ( formatStyle === "locale" ) {
580+ return num . toLocaleString ( undefined , {
581+ minimumFractionDigits : decimalPlaces ,
582+ maximumFractionDigits : decimalPlaces ,
583+ } ) ;
584+ } else if ( formatStyle === "compact" ) {
585+ if ( num >= 1000000000 ) {
586+ return ( num / 1000000000 ) . toFixed ( decimalPlaces ) + "B" ;
587+ } else if ( num >= 1000000 ) {
588+ return ( num / 1000000 ) . toFixed ( decimalPlaces ) + "M" ;
589+ } else if ( num >= 1000 ) {
590+ return ( num / 1000 ) . toFixed ( decimalPlaces ) + "K" ;
591+ } else {
592+ return num . toFixed ( decimalPlaces ) ;
593+ }
594+ }
595+
596+ return num . toFixed ( decimalPlaces ) ;
597+ }
598+
350599 _updateTimestamp ( ) {
351600 const now = new Date ( ) ;
352601 const timeStr = now . toLocaleTimeString ( ) ;
0 commit comments