diff --git a/src/components/FeaturePanel/Climbing/ClimbingView.tsx b/src/components/FeaturePanel/Climbing/ClimbingView.tsx
index 52361e0b..0cd31ae6 100644
--- a/src/components/FeaturePanel/Climbing/ClimbingView.tsx
+++ b/src/components/FeaturePanel/Climbing/ClimbingView.tsx
@@ -32,6 +32,7 @@ import MapIcon from '@mui/icons-material/Map';
import EditIcon from '@mui/icons-material/Edit';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { useGetCragViewLayout } from './utils/useCragViewLayout';
+import { RouteFloatingMenu } from './Editor/RouteFloatingMenu';
export const DEFAULT_CRAG_VIEW_LAYOUT = 'horizontal';
@@ -483,6 +484,7 @@ export const ClimbingView = ({ photo }: { photo?: string }) => {
)}
+
{
>
+
{isEditMode && }
>
diff --git a/src/components/FeaturePanel/Climbing/Editor/Points/Point.tsx b/src/components/FeaturePanel/Climbing/Editor/Points/Point.tsx
index 52c4fc33..7969021f 100644
--- a/src/components/FeaturePanel/Climbing/Editor/Points/Point.tsx
+++ b/src/components/FeaturePanel/Climbing/Editor/Points/Point.tsx
@@ -62,6 +62,7 @@ export const Point = ({
setRouteIndexHovered,
photoZoom,
getCurrentPath,
+ setIsPanningDisabled,
} = useClimbingContext();
const isMobileMode = useMobileMode();
const isPointSelected =
@@ -84,15 +85,17 @@ export const Point = ({
};
const onMouseDown = (e) => {
+ setIsPanningDisabled(true);
setPointSelectedIndex(index);
setIsPointClicked(true);
- e.preventDefault();
+ e.stopPropagation();
};
const onMouseUp = (e) => {
// @TODO unify with RouteMarks.tsx
if (!isPointMoving) {
setPointSelectedIndex(null);
+ setIsPanningDisabled(false);
onPointInSelectedRouteClick(e);
setPointElement(pointElement !== null ? null : e.currentTarget);
setPointSelectedIndex(index);
@@ -133,7 +136,7 @@ export const Point = ({
`
- transform: scale(${({ $scale }) => 1 / $scale});
+const Container = styled.div`
+ position: absolute;
+ z-index: 1;
+ bottom: 16px;
+ right: 16px;
`;
export const RouteFloatingMenu = () => {
@@ -31,7 +34,6 @@ export const RouteFloatingMenu = () => {
routes,
routeSelectedIndex,
getCurrentPath,
- photoZoom,
setRouteIndexHovered,
} = useClimbingContext();
@@ -122,8 +124,8 @@ export const RouteFloatingMenu = () => {
- {showTypeMenu ? (
-
+
+ {showTypeMenu ? (
-
- ) : (
-
+ ) : (
{machine.currentStateName === 'pointMenu' &&
routes[routeSelectedIndex] &&
@@ -216,8 +216,8 @@ export const RouteFloatingMenu = () => {
)}
-
- )}
+ )}
+
>
);
};
diff --git a/src/components/FeaturePanel/Climbing/Editor/RoutePath.tsx b/src/components/FeaturePanel/Climbing/Editor/RoutePath.tsx
index 22f26644..0d8a4abd 100644
--- a/src/components/FeaturePanel/Climbing/Editor/RoutePath.tsx
+++ b/src/components/FeaturePanel/Climbing/Editor/RoutePath.tsx
@@ -32,7 +32,7 @@ export const RoutePath = ({ route, routeNumber }) => {
routeIndexHovered,
setRouteIndexHovered,
getPathForRoute,
- photoRef,
+ svgRef,
photoZoom,
} = useClimbingContext();
const isSelected = isRouteSelected(routeNumber);
@@ -62,7 +62,7 @@ export const RoutePath = ({ route, routeNumber }) => {
units: 'px',
};
const positionInImage = getPositionInImageFromMouse(
- photoRef,
+ svgRef,
mousePosition,
photoZoom,
);
@@ -171,7 +171,8 @@ export const RoutePath = ({ route, routeNumber }) => {
cy={tempPointPosition.y}
fill="white"
stroke="rgba(0,0,0,0.3)"
- r={5}
+ r={7 / photoZoom.scale}
+ strokeWidth={1 / photoZoom.scale}
/>
)}
{machine.currentStateName === 'extendRoute' &&
diff --git a/src/components/FeaturePanel/Climbing/Editor/RoutesEditor.tsx b/src/components/FeaturePanel/Climbing/Editor/RoutesEditor.tsx
index 6b4d6506..158a22e6 100644
--- a/src/components/FeaturePanel/Climbing/Editor/RoutesEditor.tsx
+++ b/src/components/FeaturePanel/Climbing/Editor/RoutesEditor.tsx
@@ -4,9 +4,13 @@ import { RoutesLayer } from './RoutesLayer';
import { useClimbingContext } from '../contexts/ClimbingContext';
import { updateElementOnIndex } from '../utils/array';
import { PositionPx } from '../types';
-import { getPositionInImageFromMouse } from '../utils/mousePositionUtils';
+import {
+ getMouseFromPositionInImage,
+ getPositionInImageFromMouse,
+} from '../utils/mousePositionUtils';
import { getCommonsImageUrl } from '../../../../services/images/getCommonsImageUrl';
import { isMobileDevice } from '../../../helpers';
+import { RouteFloatingMenu } from './RouteFloatingMenu';
const EditorContainer = styled.div<{ imageHeight: number }>`
display: flex;
@@ -33,7 +37,7 @@ const ImageContainer = styled.div`
`;
const ImageElement = styled.img<{ zoom?: number }>`
- object-fit: contain;
+ object-fit: contain; // @TODO try to delete this
max-width: 100%;
transition: all 0.1s ease-in;
height: 100%;
@@ -61,6 +65,7 @@ export const RoutesEditor = ({
loadPhotoRelatedData,
loadedPhotos,
photoRef,
+ svgRef,
photoPath,
setLoadedPhotos,
photoZoom,
@@ -117,7 +122,7 @@ export const RoutesEditor = ({
units: 'px',
};
const positionInImage = getPositionInImageFromMouse(
- photoRef,
+ svgRef,
mousePosition,
photoZoom,
);
diff --git a/src/components/FeaturePanel/Climbing/Editor/RoutesLayer.tsx b/src/components/FeaturePanel/Climbing/Editor/RoutesLayer.tsx
index f0b0cc0c..b60ca053 100644
--- a/src/components/FeaturePanel/Climbing/Editor/RoutesLayer.tsx
+++ b/src/components/FeaturePanel/Climbing/Editor/RoutesLayer.tsx
@@ -36,12 +36,6 @@ const Svg = styled.svg<{
`}
`;
-const RouteFloatingMenuContainer = styled.div<{ $x: number; $y: number }>`
- position: absolute;
- left: ${({ $x }) => $x}px;
- top: ${({ $y }) => $y}px;
- z-index: 10000;
-`;
type Props = {
onClick: (e: any) => void;
onEditorMouseMove?: (e: any) => void;
@@ -71,8 +65,8 @@ export const RoutesLayer = ({
setPointSelectedIndex,
getCurrentPath,
routes,
- photoRef,
photoZoom,
+ svgRef,
} = useClimbingContext();
const machine = getMachine();
@@ -167,45 +161,28 @@ export const RoutesLayer = ({
? selectedPointOfSelectedRoute
: lastPointOfSelectedRoute;
- // TODO this position doesnt work well when zoomed
- const absolutePositionFromScreen = getMouseFromPositionInImage(
- photoRef,
- routeFloatingMenuPosition,
- photoZoom,
- );
-
return (
- <>
-
-
- {absolutePositionFromScreen && (
-
-
-
- )}
- >
+
);
};
diff --git a/src/components/FeaturePanel/Climbing/RouteList/ClimbingRouteTableRow.tsx b/src/components/FeaturePanel/Climbing/RouteList/ClimbingRouteTableRow.tsx
index 75105e72..a435bf3d 100644
--- a/src/components/FeaturePanel/Climbing/RouteList/ClimbingRouteTableRow.tsx
+++ b/src/components/FeaturePanel/Climbing/RouteList/ClimbingRouteTableRow.tsx
@@ -50,12 +50,14 @@ const RouteName = styled.div<{ opacity: number }>`
gap: 4px;
justify-content: space-between;
position: relative;
+ user-select: text;
`;
const RouteDescription = styled.div<{ opacity: number }>`
font-size: 10px;
opacity: ${({ opacity }) => opacity};
color: ${({ theme }) => theme.palette.text.secondary};
+ user-select: text;
`;
const RouteGrade = styled.div``;
diff --git a/src/components/FeaturePanel/Climbing/TransformWrapper.tsx b/src/components/FeaturePanel/Climbing/TransformWrapper.tsx
index decaef63..d2bf2d2a 100644
--- a/src/components/FeaturePanel/Climbing/TransformWrapper.tsx
+++ b/src/components/FeaturePanel/Climbing/TransformWrapper.tsx
@@ -4,8 +4,12 @@ import { useClimbingContext } from './contexts/ClimbingContext';
import { ZoomState } from './types';
export const TransformWrapper = ({ children }) => {
- const { setArePointerEventsDisabled, setPhotoZoom, isEditMode } =
- useClimbingContext();
+ const {
+ setArePointerEventsDisabled,
+ setPhotoZoom,
+ isEditMode,
+ isPanningDisabled,
+ } = useClimbingContext();
const startPointerEvents = () => {
setArePointerEventsDisabled(false);
@@ -31,6 +35,7 @@ export const TransformWrapper = ({ children }) => {
onPanningStart={startPointerEvents}
onPanningStop={startPointerEvents}
disablePadding
+ panning={{ disabled: isPanningDisabled }}
wheel={{ step: 100 }}
centerOnInit
onTransformed={(_ref, state: ZoomState) => {
diff --git a/src/components/FeaturePanel/Climbing/contexts/ClimbingContext.tsx b/src/components/FeaturePanel/Climbing/contexts/ClimbingContext.tsx
index ce5e16e0..c1948737 100644
--- a/src/components/FeaturePanel/Climbing/contexts/ClimbingContext.tsx
+++ b/src/components/FeaturePanel/Climbing/contexts/ClimbingContext.tsx
@@ -46,6 +46,8 @@ type ClimbingContextType = {
imageSize: ImageSize;
imageContainerSize: ImageSize;
isPointMoving: boolean;
+ isPanningDisabled: boolean;
+ setIsPanningDisabled: (isPanningDisabled: boolean) => void;
isRouteSelected: (routeNumber: number) => boolean;
isOtherRouteSelected: (routeNumber: number) => boolean;
isRouteHovered: (routeNumber: number) => boolean;
@@ -111,6 +113,7 @@ type ClimbingContextType = {
filterDifficulty: Array;
setFilterDifficulty: (filterDifficulty: Array) => void;
photoRef: React.MutableRefObject;
+ svgRef: React.MutableRefObject;
getAllRoutesPhotos: (cragPhotos: Array) => void;
showDebugMenu: boolean;
setShowDebugMenu: (showDebugMenu: boolean) => void;
@@ -142,6 +145,7 @@ export const ClimbingContextProvider = ({ children, feature }: Props) => {
const initialRoutes = osmToClimbingRoutes(feature);
publishDbgObject('climbingRoutes', initialRoutes);
const photoRef = useRef(null);
+ const svgRef = useRef(null);
const [photoPaths, setPhotoPaths] = useState>(null);
const [photoPath, setPhotoPath] = useState(null); // photo, should be null
const [showDebugMenu, setShowDebugMenu] = useState(false);
@@ -155,6 +159,7 @@ export const ClimbingContextProvider = ({ children, feature }: Props) => {
const [routes, setRoutes] = useState>(initialRoutes);
const [splitPaneSize, setSplitPaneSize] = useState(null);
const [isPointMoving, setIsPointMoving] = useState(false);
+ const [isPanningDisabled, setIsPanningDisabled] = useState(false);
const [isPointClicked, setIsPointClicked] = useState(false);
const [areRoutesLoading, setAreRoutesLoading] = useState(true);
const [arePointerEventsDisabled, setArePointerEventsDisabled] =
@@ -270,7 +275,7 @@ export const ClimbingContextProvider = ({ children, feature }: Props) => {
updateRouteOnIndex,
getPercentagePosition,
findCloserPoint,
- photoRef,
+ svgRef,
photoZoom,
});
@@ -323,6 +328,8 @@ export const ClimbingContextProvider = ({ children, feature }: Props) => {
imageSize,
isPointClicked,
isPointMoving,
+ isPanningDisabled,
+ setIsPanningDisabled,
isRouteSelected,
isOtherRouteSelected,
isRouteHovered,
@@ -366,7 +373,8 @@ export const ClimbingContextProvider = ({ children, feature }: Props) => {
loadPhotoRelatedData,
filterDifficulty,
setFilterDifficulty,
- photoRef,
+ photoRef, // @TODO rename: technically it's not photoRef but photoContainerRef, because photo is scaled by object-fit: contain
+ svgRef,
areRoutesLoading,
setAreRoutesLoading,
photoZoom,
diff --git a/src/components/FeaturePanel/Climbing/utils/mousePositionUtils.ts b/src/components/FeaturePanel/Climbing/utils/mousePositionUtils.ts
index 29b4fbbc..70edb222 100644
--- a/src/components/FeaturePanel/Climbing/utils/mousePositionUtils.ts
+++ b/src/components/FeaturePanel/Climbing/utils/mousePositionUtils.ts
@@ -2,15 +2,15 @@ import React from 'react';
import { PositionPx, ZoomState } from '../types';
export const getPositionInImageFromMouse = (
- photoRef: React.MutableRefObject,
+ svgRef: React.MutableRefObject,
mousePosition: PositionPx,
photoZoom: ZoomState,
) => {
- if (photoRef.current === null || !mousePosition) {
+ if (svgRef.current === null || !mousePosition) {
return null;
}
- const imageRect = photoRef.current.getBoundingClientRect();
+ const imageRect = svgRef.current.getBoundingClientRect();
const posInImage: PositionPx = {
x: (mousePosition.x - imageRect.x) / photoZoom.scale,
@@ -21,15 +21,15 @@ export const getPositionInImageFromMouse = (
};
export const getMouseFromPositionInImage = (
- photoRef: React.MutableRefObject,
+ svgRef: React.MutableRefObject,
position: PositionPx,
photoZoom: ZoomState,
) => {
- if (photoRef.current === null || !position) {
+ if (svgRef.current === null || !position) {
return null;
}
- const imageRect = photoRef.current.getBoundingClientRect();
+ const imageRect = svgRef.current.getBoundingClientRect();
return {
x: position.x * photoZoom.scale + imageRect.x,
diff --git a/src/components/FeaturePanel/Climbing/utils/useGetMachineFactory.ts b/src/components/FeaturePanel/Climbing/utils/useGetMachineFactory.ts
index dae96db7..4fd5fc4e 100644
--- a/src/components/FeaturePanel/Climbing/utils/useGetMachineFactory.ts
+++ b/src/components/FeaturePanel/Climbing/utils/useGetMachineFactory.ts
@@ -49,7 +49,7 @@ export const useGetMachineFactory = ({
updateRouteOnIndex,
getPercentagePosition,
findCloserPoint,
- photoRef,
+ svgRef,
photoZoom,
}) => {
const [currentState, setCurrentState] = useState('init');
@@ -132,7 +132,7 @@ export const useGetMachineFactory = ({
const addPointToEnd = (props: { position: PositionPx }) => {
if (!props) return;
const positionInImage = getPositionInImageFromMouse(
- photoRef,
+ svgRef,
props.position,
photoZoom,
);