+import axios from 'axios';
import OpenSeadragon from 'openseadragon';
import PropTypes from 'prop-types';
import React from 'react';
+import { useNavigate, useParams } from 'react-router';
+import { createSearchParams, useSearchParams } from 'react-router-dom';
export const Context = React.createContext({});
export const useOpenSeadragon = () => React.useContext(Context);
export const Provider = React.forwardRef(({ children }, ref) => {
+ const { activeMap } = useParams();
+ const navigate = useNavigate();
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [pins, setPins] = React.useState([]);
const [viewer, setViewer] = React.useState(null);
+ const storePosition = React.useCallback(() => {
+ if (!viewer || !viewer.viewport) return;
+ const center = viewer.viewport.getCenter();
+ const zoom = viewer.viewport.getZoom();
+ setSearchParams({ x: center.x, y: center.y, z: zoom }, { replace: true });
+ }, [setSearchParams, viewer]);
+
+ const setActiveMap = React.useCallback(map => {
+ if (viewer && viewer.viewport) {
+ const center = viewer.viewport.getCenter();
+ const zoom = viewer.viewport.getZoom();
+ const params = { x: center.x, y: center.y, z: zoom };
+ navigate(
+ { pathname: `../${map}`, search: `?${createSearchParams(params)}` },
+ { replace: true },
+ );
+ } else {
+ navigate(`../${map}`, { replace: true });
+ }
+ }, [navigate, viewer]);
+
+ React.useEffect(() => {
+ if (!viewer || !viewer.viewport) return;
+ if (searchParams.has('x') && searchParams.has('y')) {
+ viewer.viewport.panTo(new OpenSeadragon.Point(
+ parseFloat(searchParams.get('x')),
+ parseFloat(searchParams.get('y')),
+ ));
+ }
+ if (searchParams.has('z')) {
+ viewer.viewport.zoomTo(parseFloat(searchParams.get('z')));
+ }
+ }, [searchParams, viewer]);
+
React.useEffect(() => {
if (!ref.current) return;
maxLevel: 14,
tilesUrl: '/media/alttp/map/uw_files/',
fileFormat: 'png',
+ }), new OpenSeadragon.DziTileSource({
+ width: 16384,
+ height: 3072,
+ tileSize: 256,
+ tileOverlap: 0,
+ minLevel: 8,
+ maxLevel: 14,
+ tilesUrl: '/media/alttp/map/uw2_files/',
+ fileFormat: 'png',
}),
],
});
+ v.addHandler('canvas-nonprimary-press', e => {
+ if (e.button === 3) {
+ navigate(-1);
+ } else if (e.button === 4) {
+ navigate(1);
+ }
+ });
setViewer(v);
return () => {
v.destroy();
};
}, [ref.current]);
- return <Context.Provider value={{ viewer }}>
+ React.useEffect(() => {
+ if (!viewer) return;
+ switch (activeMap) {
+ case 'lw':
+ viewer.goToPage(0);
+ break;
+ case 'dw':
+ viewer.goToPage(1);
+ break;
+ case 'sp':
+ viewer.goToPage(2);
+ break;
+ case 'uw':
+ viewer.goToPage(3);
+ break;
+ case 'uw2':
+ viewer.goToPage(4);
+ break;
+ }
+ const controller = new AbortController();
+ axios.get(`/api/markers/${activeMap}`, {
+ signal: controller.signal,
+ }).then(response => {
+ setPins(response.data || []);
+ }).catch(e => {
+ if (!axios.isCancel(e)) {
+ console.error(e);
+ }
+ });
+ return () => {
+ controller.abort();
+ };
+ }, [activeMap, viewer]);
+
+ return <Context.Provider value={{ activeMap, pins, setActiveMap, storePosition, viewer }}>
{children}
</Context.Provider>;
});