From ce967f159d43e7a939d0f96d864ad7b9b44dbcc0 Mon Sep 17 00:00:00 2001 From: Timothy Armes Date: Mon, 30 Sep 2024 16:34:35 +0200 Subject: [PATCH] Use better touch gestures --- package.json | 1 + src/components/MapEvents.tsx | 39 +++++++++++++++++++++++++++++++++--- src/messages/en.json | 6 ++++++ src/messages/fr.json | 6 ++++++ yarn.lock | 27 +++++++++++++++++++++---- 5 files changed, 72 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ac833cf..3961d3c 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "jotai": "^2.6.1", "leaflet": "^1.9.4", "leaflet-defaulticon-compatibility": "^0.1.2", + "leaflet-gesture-handling": "^1.2.2", "leaflet.markercluster": "^1.5.3", "leaflet.smooth_marker_bouncing": "^3.0.3", "lodash": "^4.17.21", diff --git a/src/components/MapEvents.tsx b/src/components/MapEvents.tsx index b3f5710..6dcdb1b 100644 --- a/src/components/MapEvents.tsx +++ b/src/components/MapEvents.tsx @@ -2,11 +2,21 @@ import { useEffect, useTransition } from "react"; import { useSetAtom } from "jotai"; import L from "leaflet"; -import { useMapEvent } from "react-leaflet"; +import { GestureHandling } from "leaflet-gesture-handling"; +import "leaflet-gesture-handling/dist/leaflet-gesture-handling.css"; +import "leaflet/dist/leaflet.css"; +import { useLocale, useTranslations } from "next-intl"; +import { useMap, useMapEvent } from "react-leaflet"; import { mapBoundsAtom } from "@/atoms"; +// Add Leaflet.GestureHandling for improved desktop and mobile touch gestures +L.Map.addInitHook("addHandler", "gestureHandling", GestureHandling); + const MapEvents = () => { + const locale = useLocale(); + const t = useTranslations("Map"); + const map = useMap(); const setMapBounds = useSetAtom(mapBoundsAtom); const [isPending, startTransition] = useTransition(); @@ -16,7 +26,7 @@ const MapEvents = () => { L.latLng(51.17, 9.53), ); - const map = useMapEvent("moveend", () => { + useMapEvent("moveend", () => { // Set the map bounds atoms when the user pans/zooms startTransition(() => { setMapBounds(map.getBounds()); @@ -28,7 +38,30 @@ const MapEvents = () => { map.setView(franceBounds.getCenter(), map.getBoundsZoom(franceBounds)); map.setMaxBounds(worldBounds); map.options.maxBoundsViscosity = 1.0; // Prevents going past bounds while dragging - }, []); // eslint-disable-line react-hooks/exhaustive-deps + + map.addHandler("gestureHandling", GestureHandling); + + // @ts-expect-error Typescript does not see additional handler here + map.gestureHandling.enable(); + }, [map]); + + useEffect(() => { + console.log("setting map language", locale); + // @ts-expect-error Typescript does not see additional handler here + map.options.gestureHandlingOptions.text = { + touch: t("touch"), + scroll: t("scroll"), + scrollMac: t("scrollMac"), + }; + + // We need to toggle the handler to update the text on prod. No idea why. + + // @ts-expect-error Typescript does not see additional handler here + map.gestureHandling.disable(); + + // @ts-expect-error Typescript does not see additional handler here + map.gestureHandling.enable(); + }, [map, locale]); return null; }; diff --git a/src/messages/en.json b/src/messages/en.json index 86dca41..a33066b 100644 --- a/src/messages/en.json +++ b/src/messages/en.json @@ -59,6 +59,12 @@ "getInvolved": "Echecs France is completely free, open source and open to contributions. Find us on GitHub if you want to get involved." }, + "Map": { + "touch": "Use two fingers to move the map", + "scroll": "Use ctrl + scroll to zoom the map", + "scrollMac": "Use \u2318 + scroll to zoom the map" + }, + "Tournaments": { "loading": "Loading...", "searchLabel": "Search", diff --git a/src/messages/fr.json b/src/messages/fr.json index 390ed08..6e9f269 100644 --- a/src/messages/fr.json +++ b/src/messages/fr.json @@ -58,6 +58,12 @@ "getInvolved": "Échecs France est complètement gratuit, open source et ouvert aux contributions. Retrouvez-nous sur GitHub si vous souhaitez vous impliquer." }, + "Map": { + "touch": "Utilisez deux doigts pour déplacer la carte", + "scroll": "Utilisez ctrl + défilement pour zoomer sur la carte", + "scrollMac": "Utilisez \u2318 + défilement pour zoomer sur la carte" + }, + "Tournaments": { "loading": "Téléchargement...", "searchLabel": "Rechercher", diff --git a/yarn.lock b/yarn.lock index 90b21f9..d488ad7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3965,6 +3965,11 @@ leaflet-defaulticon-compatibility@^0.1.2: resolved "https://registry.yarnpkg.com/leaflet-defaulticon-compatibility/-/leaflet-defaulticon-compatibility-0.1.2.tgz#f5e1a5841aeab9d1682d17887348855a741b3c2a" integrity sha512-IrKagWxkTwzxUkFIumy/Zmo3ksjuAu3zEadtOuJcKzuXaD76Gwvg2Z1mLyx7y52ykOzM8rAH5ChBs4DnfdGa6Q== +leaflet-gesture-handling@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/leaflet-gesture-handling/-/leaflet-gesture-handling-1.2.2.tgz#ea10afb94f2d477d77d47beb21e409ed327df07a" + integrity sha512-Blf5V4PoNphWkzL7Y1qge+Spkd4OCQ2atjwUNhMhLIcjKzPcBH++x/lwOinaR9jSqLWqJ6oKYO8d0XdTffy4hQ== + leaflet.markercluster@^1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz#9cdb52a4eab92671832e1ef9899669e80efc4056" @@ -5211,8 +5216,16 @@ streamsearch@^1.1.0: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5285,8 +5298,14 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - name strip-ansi-cjs +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==