From c43d387f1f188b3a33fcdf6886bc2df4ff6b5fd0 Mon Sep 17 00:00:00 2001 From: Jeran Date: Sat, 29 Aug 2026 16:26:32 +0200 Subject: [PATCH] updated UI --- src/GlobalStates/GlobalStore.ts | 1 + .../ui/NavBar/ExportImageSettings.tsx | 2 + src/components/ui/NavBar/ParameterExport.tsx | 189 ++++++++++++++---- src/components/ui/NavBar/PerformanceMode.tsx | 18 +- 4 files changed, 167 insertions(+), 43 deletions(-) diff --git a/src/GlobalStates/GlobalStore.ts b/src/GlobalStates/GlobalStore.ts index d17d7ba65..51b546ff6 100644 --- a/src/GlobalStates/GlobalStore.ts +++ b/src/GlobalStates/GlobalStore.ts @@ -221,6 +221,7 @@ declare global { var __appStore: UseBoundStore> | undefined } +export const defaultGlobals = createStore().getState() // Supposedly this makes it a global that cannot be duplicated by Next into different code chunks export const useGlobalStore = diff --git a/src/components/ui/NavBar/ExportImageSettings.tsx b/src/components/ui/NavBar/ExportImageSettings.tsx index d1e3dc529..3a75608c4 100644 --- a/src/components/ui/NavBar/ExportImageSettings.tsx +++ b/src/components/ui/NavBar/ExportImageSettings.tsx @@ -89,6 +89,7 @@ const ExportImageSettings = () => { +
+
, keys: string[]) { return Object.fromEntries( @@ -85,7 +89,6 @@ const zarrValues = [ 'axisMapping', 'compress', 'useNC', // This one is more static and so toggling switch doesn't break all other logic - 'fetchNC', 'coarsen', 'kernelSize', 'kernelDepth', @@ -98,62 +101,176 @@ const zarrValues = [ export const ParameterExport = () => { const [copied, setCopied] = useState(false); + const [copiedLoc, setCopiedLoc] = useState([0,0]) + const [exportVal, setExportVal] = useState("Full State"); + const states = ['Full State', 'Keyframes', 'Camera']; - function generateURL(){ - const {cameraRef} = useImageExportStore.getState() + const getGlobalStateJSON = () =>{ + const {cameraRef} = useImageExportStore.getState(); usePlotStore.setState({cameraPosition:cameraRef?.current?.position}) // Set Camera position first to copy visual state const fullObj = { globalState: pick(useGlobalStore.getState(), globalValues), plotState: pick(usePlotStore.getState(), plotValues), zarrState: pick(useZarrStore.getState(), zarrValues), } - const jString = JSON.stringify(fullObj, (_, v) => typeof v === 'bigint' ? v.toString() : v) - const params = `https://browzarr.io/latest/?data=${encodeURIComponent(jString)}` - return params + return JSON.stringify(fullObj, (_, v) => typeof v === 'bigint' ? v.toString() : v);; + } + + const getJSON = () =>{ + if (exportVal === "Full State"){ + return getGlobalStateJSON() + } else if (exportVal === "Camera"){ + const {cameraRef} = useImageExportStore.getState(); + const position = cameraRef?.current?.position; + //@ts-ignore zoom does exist + const zoom = cameraRef?.current?.zoom; + const cameraObj = { + position, + ...(zoom && { zoom }) + }; + return JSON.stringify(cameraObj, null, 2); + } else { + const {keyFrames} = useImageExportStore.getState(); + return JSON.stringify(keyFrames?? {}, null, 2) + } + } + + function generateURL(){ + let jString; + if (exportVal === "Full State")jString = getGlobalStateJSON(); + else jString = JSON.stringify( + {plotState: {cameraPosition: usePlotStore.getState().cameraPosition}}, null, 2 + ); + const params = `https://browzarr.io/latest/?data=${encodeURIComponent(jString)}`; + return params; } - const copyToClipboard = async () => { - const url = generateURL() - await navigator.clipboard.writeText(url); + const copyToClipboard = async (e: React.MouseEvent, text:string) => { + const {pageX, pageY} = e + setCopiedLoc([pageX, pageY]) + await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 1500); //Use for a pop-up that fades away }; - + + const copyJSON = (e:React.MouseEvent) => copyToClipboard(e, getJSON()); + const copyURL = (e: React.MouseEvent) => copyToClipboard(e, generateURL()); + + const exportToJSON = () => { + const blob = new Blob([getJSON()], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + + const link = document.createElement('a'); + link.href = url; + link.download = `${exportVal}.json`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + URL.revokeObjectURL(url); + } + + const isKeyframes = exportVal == 'Keyframes'; return ( - + +
+ +
+
- -
- Copied! -
+
+ Export State + +
+
+ {/* JSON Options */} +
+
+ + +
+
+ + +
+
+
+ + +
+
+ +
+ {createPortal(
+
+ Copied! +
+
, document.body) + }
) diff --git a/src/components/ui/NavBar/PerformanceMode.tsx b/src/components/ui/NavBar/PerformanceMode.tsx index efdedaa4e..492cd0a3d 100644 --- a/src/components/ui/NavBar/PerformanceMode.tsx +++ b/src/components/ui/NavBar/PerformanceMode.tsx @@ -6,6 +6,7 @@ import { FaCarSide } from "react-icons/fa6"; import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover" import { useGlobalStore } from '@/GlobalStates/GlobalStore'; import { Button } from "@/components/ui/button-enhanced" +import { QuickTip } from '../Widgets/QuickTip'; const icons = { "fast": , @@ -29,13 +30,16 @@ const PerformanceMode = () => { - + + + +