-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathuseSettings.tsx
102 lines (92 loc) · 3.33 KB
/
useSettings.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { RefObject, useCallback, useEffect, useRef } from 'react';
import { CurrencyTicker } from '../../../../../config/config/currencies';
import { useStoreContext } from '../../../../../store/useStore';
import { setCurrency } from '../../../../fiat/store/useFiatActions';
import { useSelectCurrency } from '../../../../fiat/store/useFiatSelectors';
import { useSelectActiveAccountAddress } from '../../../../wallet/store/useWalletSelectors';
import { useSelectWidgetsLayout } from '../../WidgetsLayout/store/useWidgetsLayoutSelectors';
import { WidgetsLayoutState } from '../../WidgetsLayout/store/useWidgetsLayoutStore';
export interface UseSettingsReturn {
handleSettingsExport: () => void;
handleSettingsImport: () => void;
importSettings: (u: React.ChangeEvent<HTMLInputElement>) => void;
settingsFileInputRef: RefObject<HTMLInputElement>;
}
export interface PersistableSettings {
widgetLayout: WidgetsLayoutState;
currency: CurrencyTicker;
}
export const useSettings = (): UseSettingsReturn => {
// TODO: add currency persisting as part of settings
const [, dispatch] = useStoreContext();
const settings = useSelectWidgetsLayout();
const address = useSelectActiveAccountAddress();
// ref to the hidden file input element
const settingsFileInputRef = useRef<HTMLInputElement>(null);
const currency = useSelectCurrency();
useEffect(() => {
const persistableSettings: PersistableSettings = {
widgetLayout: settings,
currency,
};
window.localStorage.setItem(
'STATE_LAYOUT',
JSON.stringify(persistableSettings)
);
}, [settings, currency]);
// saves a file with the current widget settings including widget layout
const handleSettingsExport = useCallback((): void => {
if (!address) return;
const a = document.createElement('a');
const persistableSettings: PersistableSettings = {
widgetLayout: settings,
currency,
};
const file = new Blob([JSON.stringify(persistableSettings)], {
type: 'text/plain',
});
a.href = URL.createObjectURL(file);
a.download = `${address}-portfolio-dashboard-settings.json`;
a.click();
}, [settings, address, currency]);
// imports layout/widget settings from a JSON file uploaded by the user
const importSettings = useCallback(
(e: React.ChangeEvent<HTMLInputElement>): void => {
if (e.target.files?.[0]) {
const fileReader = new FileReader();
fileReader.readAsText(e.target.files[0], 'UTF-8');
fileReader.onload = (e) => {
const settings = JSON.parse(
e.target?.result?.toString() ?? ''
) as PersistableSettings;
if (
!(
'widgets' in settings.widgetLayout &&
'layout' in settings.widgetLayout
) ||
!settings.currency
)
return;
if (settings) {
dispatch(setCurrency(settings.currency));
dispatch({
type: 'SET_LAYOUT',
payload: settings.widgetLayout,
});
}
};
}
},
[]
);
// trigger file input on a hidden settings file input
const handleSettingsImport = useCallback(() => {
settingsFileInputRef.current?.click();
}, [settingsFileInputRef]);
return {
importSettings,
settingsFileInputRef,
handleSettingsExport,
handleSettingsImport,
};
};