From 7bad27402a8e2799d486c132262378da8a093d00 Mon Sep 17 00:00:00 2001 From: "Tanner Collin (aider)" Date: Thu, 14 Aug 2025 23:36:40 +0000 Subject: [PATCH] feat: add share range button to copy shareable URL --- mapper/src/App.js | 56 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) 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 + }