diff --git a/mapper/src/App.js b/mapper/src/App.js
index 3898220..7857ebe 100644
--- a/mapper/src/App.js
+++ b/mapper/src/App.js
@@ -37,12 +37,12 @@ const parseSlider = (end, duration, slider) => {
return [lowStr, highStr];
};
-//async function sha256(source) {
-// const sourceBytes = new TextEncoder().encode(source);
-// const digest = await crypto.subtle.digest('SHA-26', sourceBytes);
-// const resultBytes = [...new Uint8Array(digest)];
-// return resultBytes.map(x => x.toString(16).padStart(2, '0')).join('');
-//}
+async function sha256(source) {
+ const sourceBytes = new TextEncoder().encode(source);
+ const digest = await crypto.subtle.digest('SHA-256', sourceBytes);
+ const resultBytes = [...new Uint8Array(digest)];
+ return resultBytes.map(x => x.toString(16).padStart(2, '0')).join('');
+}
function useSensor(measurement, name, end, duration) {
const [data, setData] = useState(false);
@@ -52,8 +52,19 @@ function useSensor(measurement, name, end, duration) {
const get = async() => {
setLoading(true);
try {
- const api_key = localStorage.getItem('api_key', 'null');
+ const api_key = localStorage.getItem('api_key');
+ const urlParams = new URLSearchParams(window.location.search);
+ const shareStart = urlParams.get('shareStart');
+ const shareEnd = urlParams.get('shareEnd');
+ const shareSig = urlParams.get('shareSig');
const params = { end: end.unix(), duration: duration.len.toLowerCase(), window: duration.win, api_key: api_key };
+
+ if (shareStart && shareEnd && shareSig) {
+ params.shareStart = shareStart;
+ params.shareEnd = shareEnd;
+ params.shareSig = shareSig;
+ }
+
const res = await axios.get(
'https://sensors-api.dns.t0.vc/history/'+measurement+'/'+name,
{ params: params },
@@ -321,6 +332,36 @@ function Menu({duration, setDuration, end, setEnd, slider, setSlider, submenu, s
const range = parseSlider(end, duration, slider);
+ const shareRange = async () => {
+ const shareStart = moment(range[0]).unix();
+ const shareEnd = moment(range[1]).unix();
+ const apiKey = localStorage.getItem('api_key');
+
+ if (!apiKey) {
+ alert('API key is not set. Cannot create a shareable link.');
+ return;
+ }
+
+ const dataToSign = `${shareStart}-${shareEnd}-${apiKey}`;
+ const shareSig = await sha256(dataToSign);
+
+ const params = new URLSearchParams(window.location.search);
+ params.set('shareStart', shareStart);
+ params.set('shareEnd', shareEnd);
+ params.set('shareSig', shareSig);
+
+ const shareUrl = `${window.location.origin}${window.location.pathname}?${params.toString()}`;
+
+ try {
+ await navigator.clipboard.writeText(shareUrl);
+ alert('Shareable URL copied to clipboard!');
+ } catch (err) {
+ console.error('Failed to copy: ', err);
+ alert('Failed to copy URL to clipboard.');
+ }
+ setSubmenu(false);
+ };
+
const rangeTime = (x) => {
if (new Date().getTimezoneOffset()) { // non-librewolf browser
return moment(x).format('lll'); // default to browser's TZ
@@ -439,6 +480,7 @@ function Menu({duration, setDuration, end, setEnd, slider, setSlider, submenu, s
/>
Show direction
+
>
}