@@ -28,39 +28,84 @@ const STORAGE_KEYS = {
2828 decimalPlaces : "flowfi-decimal-places" ,
2929} ;
3030
31+ let sharedSettings : Settings = { ...DEFAULT_SETTINGS } ;
32+ let sharedIsHydrated = false ;
33+ const listeners = new Set < ( ) => void > ( ) ;
34+
35+ function notifyListeners ( ) {
36+ listeners . forEach ( ( listener ) => listener ( ) ) ;
37+ }
38+
39+ function loadSettingsFromStorage ( ) : Settings {
40+ if ( typeof window === "undefined" ) return { ...DEFAULT_SETTINGS } ;
41+ const savedTheme = localStorage . getItem ( STORAGE_KEYS . theme ) as Theme | null ;
42+ const savedCurrency = localStorage . getItem (
43+ STORAGE_KEYS . displayCurrency
44+ ) as DisplayCurrency | null ;
45+ const savedFormat = localStorage . getItem (
46+ STORAGE_KEYS . amountFormat
47+ ) as AmountFormat | null ;
48+ const savedDecimals = localStorage . getItem ( STORAGE_KEYS . decimalPlaces ) ;
49+
50+ return {
51+ theme : savedTheme || DEFAULT_SETTINGS . theme ,
52+ displayCurrency : savedCurrency || DEFAULT_SETTINGS . displayCurrency ,
53+ amountFormat : savedFormat || DEFAULT_SETTINGS . amountFormat ,
54+ decimalPlaces : savedDecimals
55+ ? ( parseInt ( savedDecimals , 10 ) as DecimalPlaces )
56+ : DEFAULT_SETTINGS . decimalPlaces ,
57+ } ;
58+ }
59+
60+ if ( typeof window !== "undefined" ) {
61+ window . addEventListener ( "storage" , ( e ) => {
62+ if ( ! e . key || Object . values ( STORAGE_KEYS ) . includes ( e . key ) ) {
63+ sharedSettings = loadSettingsFromStorage ( ) ;
64+ sharedIsHydrated = true ;
65+ notifyListeners ( ) ;
66+ }
67+ } ) ;
68+ }
69+
70+ // For testing purposes
71+ export function _resetSharedSettings ( ) {
72+ sharedSettings = { ...DEFAULT_SETTINGS } ;
73+ sharedIsHydrated = false ;
74+ listeners . clear ( ) ;
75+ }
76+
3177export function useSettings ( ) {
32- const [ settings , setSettings ] = useState < Settings > ( DEFAULT_SETTINGS ) ;
33- const [ isHydrated , setIsHydrated ] = useState ( false ) ;
78+ const [ settings , setSettingsState ] = useState < Settings > ( sharedSettings ) ;
79+ const [ isHydrated , setIsHydrated ] = useState ( sharedIsHydrated ) ;
3480
3581 useEffect ( ( ) => {
36- if ( typeof window === "undefined" ) return ;
37-
38- const savedTheme = localStorage . getItem ( STORAGE_KEYS . theme ) as Theme | null ;
39- const savedCurrency = localStorage . getItem (
40- STORAGE_KEYS . displayCurrency
41- ) as DisplayCurrency | null ;
42- const savedFormat = localStorage . getItem (
43- STORAGE_KEYS . amountFormat
44- ) as AmountFormat | null ;
45- const savedDecimals = localStorage . getItem ( STORAGE_KEYS . decimalPlaces ) ;
46-
47- // Use queueMicrotask to avoid synchronous setState in effect
48- queueMicrotask ( ( ) => {
49- setSettings ( {
50- theme : savedTheme || DEFAULT_SETTINGS . theme ,
51- displayCurrency : savedCurrency || DEFAULT_SETTINGS . displayCurrency ,
52- amountFormat : savedFormat || DEFAULT_SETTINGS . amountFormat ,
53- decimalPlaces : savedDecimals
54- ? ( parseInt ( savedDecimals , 10 ) as DecimalPlaces )
55- : DEFAULT_SETTINGS . decimalPlaces ,
82+ const listener = ( ) => {
83+ setSettingsState ( sharedSettings ) ;
84+ setIsHydrated ( sharedIsHydrated ) ;
85+ } ;
86+ listeners . add ( listener ) ;
87+
88+ if ( ! sharedIsHydrated && typeof window !== "undefined" ) {
89+ queueMicrotask ( ( ) => {
90+ if ( ! sharedIsHydrated ) {
91+ sharedSettings = loadSettingsFromStorage ( ) ;
92+ sharedIsHydrated = true ;
93+ notifyListeners ( ) ;
94+ }
5695 } ) ;
57- setIsHydrated ( true ) ;
58- } ) ;
96+ } else {
97+ listener ( ) ;
98+ }
99+
100+ return ( ) => {
101+ listeners . delete ( listener ) ;
102+ } ;
59103 } , [ ] ) ;
60104
61105 const setTheme = useCallback ( ( theme : Theme ) => {
62- setSettings ( ( prev ) => ( { ...prev , theme } ) ) ;
106+ sharedSettings = { ...sharedSettings , theme } ;
63107 localStorage . setItem ( STORAGE_KEYS . theme , theme ) ;
108+ notifyListeners ( ) ;
64109
65110 // Apply theme immediately
66111 if ( theme === "system" ) {
@@ -72,18 +117,21 @@ export function useSettings() {
72117 } , [ ] ) ;
73118
74119 const setDisplayCurrency = useCallback ( ( currency : DisplayCurrency ) => {
75- setSettings ( ( prev ) => ( { ...prev , displayCurrency : currency } ) ) ;
120+ sharedSettings = { ...sharedSettings , displayCurrency : currency } ;
76121 localStorage . setItem ( STORAGE_KEYS . displayCurrency , currency ) ;
122+ notifyListeners ( ) ;
77123 } , [ ] ) ;
78124
79125 const setAmountFormat = useCallback ( ( format : AmountFormat ) => {
80- setSettings ( ( prev ) => ( { ...prev , amountFormat : format } ) ) ;
126+ sharedSettings = { ...sharedSettings , amountFormat : format } ;
81127 localStorage . setItem ( STORAGE_KEYS . amountFormat , format ) ;
128+ notifyListeners ( ) ;
82129 } , [ ] ) ;
83130
84131 const setDecimalPlaces = useCallback ( ( places : DecimalPlaces ) => {
85- setSettings ( ( prev ) => ( { ...prev , decimalPlaces : places } ) ) ;
132+ sharedSettings = { ...sharedSettings , decimalPlaces : places } ;
86133 localStorage . setItem ( STORAGE_KEYS . decimalPlaces , places . toString ( ) ) ;
134+ notifyListeners ( ) ;
87135 } , [ ] ) ;
88136
89137 return {
0 commit comments