Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/garden privacy #333

Merged
merged 4 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib/components/Chat/ConversationCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
display: inline-flex;
}

@media (min-width: 700px) and (max-width: 850px) {
@media (min-width: 701px) and (max-width: 850px) {
.conversation {
padding: 1rem 1.4rem;
}
Expand Down
15 changes: 13 additions & 2 deletions src/lib/components/Map/GardenLayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { getContext, createEventDispatcher } from 'svelte';
import key from './mapbox-context.js';
import { tentIcon } from '$lib/images/markers';
import { nonMemberMaxZoom } from '$lib/constants';

type GardenFeatureCollection = {
type: 'FeatureCollection';
Expand Down Expand Up @@ -209,7 +210,13 @@
type: 'geojson',
data: fcAllGardens,
cluster: true,
clusterMaxZoom: 14,
/** Max zoom on which to cluster points if clustering is enabled.
* Defaults to one zoom less than maxzoom (so that last zoom features are not clustered).
* https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#geojson-clusterMaxZoom
*
* Note: the non-member max zoom should be more zoomed out than the member max zoom.
*/
clusterMaxZoom: nonMemberMaxZoom - 1,
clusterRadius: 50
});

Expand Down Expand Up @@ -248,6 +255,7 @@
layout: {
'text-field': '{point_count_abbreviated}',
'text-size': 13
// 'text-allow-overlap': true
}
});

Expand All @@ -258,7 +266,10 @@
filter: ['!', ['has', 'point_count']],
layout: {
'icon-image': ['get', 'icon'],
'icon-size': 0.4
'icon-size': 0.4,
// Needs to be true, otherwise a city/town name on the map will overlap a garden.
// http://localhost:5173/explore/garden/XFVhmDog6xQprHRJuy1UkThRUVh2 and the name "Spalbeek"
'icon-allow-overlap': true
}
});

Expand Down
5 changes: 4 additions & 1 deletion src/lib/components/Map/Map.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
import key from './mapbox-context.js';

import 'maplibre-gl/dist/maplibre-gl.css';
import { DEFAULT_MAP_STYLE } from '$lib/constants.js';
import { DEFAULT_MAP_STYLE, memberMaxZoom, nonMemberMaxZoom } from '$lib/constants.js';
import FullscreenControl from './FullscreenControl.js';
import { isFullscreen } from '$lib/stores/fullscreen.js';
import { user } from '$lib/stores/auth.js';

export let lat: number;
export let lon: number;
Expand Down Expand Up @@ -75,6 +76,8 @@
style: DEFAULT_MAP_STYLE,
center: [lon, lat],
zoom,
/** https://docs.mapbox.com/mapbox-gl-js/api/map/#map-parameters */
maxZoom: $user?.superfan ? memberMaxZoom : nonMemberMaxZoom,
attributionControl: false,
hash: false // TODO: discuss if we want this or not
});
Expand Down
112 changes: 112 additions & 0 deletions src/lib/components/Map/ZoomRestrictionNotice.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { user } from '$lib/stores/auth';
import { getContext, onDestroy } from 'svelte';
import type { ContextType } from './Map.svelte';
import key from './mapbox-context.js';
import type { Map, MapEventType, EventData } from 'maplibre-gl';
import { nonMemberMaxZoom } from '$lib/constants';
import { fade } from 'svelte/transition';
import { Anchor } from '../UI';
import createUrl from '$lib/util/create-url';
import routes from '$lib/routes';
import { PlausibleEvent } from '$lib/types/Plausible';
const { getMap } = getContext<ContextType>(key);
const map = getMap();

let showNotice = false;

/**
* Determines if the zoom restriciton notice should be shown for map instance in its current state,
* and displays it if so.
*/
function toggleNoticeOnMapZoom(map: Map) {
if (map.getZoom() >= nonMemberMaxZoom) {
showNotice = true;
} else {
showNotice = false;
}
}

const zoomEventHandler = (e: MapEventType['zoom'] & EventData) => {
toggleNoticeOnMapZoom(e.target);
};

if (!$user?.superfan) {
// Show the notice on load time if needed.
toggleNoticeOnMapZoom(map);

// Using this event instead of 'zoomend' results in a more responsive appearance of the notice.
map.on('zoom', zoomEventHandler);
}

onDestroy(() => {
map.off('zoom', zoomEventHandler);
});
</script>

{#if showNotice}
<div transition:fade>
<p>
ℹ️{' '}
<Anchor
href={createUrl(routes.ABOUT_MEMBERSHIP)}
track={[PlausibleEvent.VISIT_ABOUT_MEMBERSHIP, { source: 'zoom_notice' }]}
newtab>{$_('generics.become-member')}</Anchor
>{' '}{$_('map.zoom-restriction-notice')}.
</p>
</div>
{/if}

<style>
div {
padding: 4px 8px;
border-radius: 10px;
/* Same as the layers & tools background */
background-color: rgba(255, 255, 255, 0.9);
position: absolute;
/* Same as the filter box */
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);
/* Make it possible to drag the map below the notice.
Should be complemented with an exception for the link inside (see below) */
pointer-events: none;
}

/* Make the link clickable */
div :global(a) {
pointer-events: auto;
}

/* TODO: the absolute positioning here is dependent on the sizing of other components overlaying the map.
* Some of those components are not <Map> children, but this component needs to be a child of Map's context to listen to map zoom events.
* This hacky approach of absolute positioning from different component parents is now deemed preferrable over refactoring the component structures
* so that they are positioned relative to eachother with e.g. flexbox or such.
*/

/* Mobile */
@media screen and (max-width: 700px) {
div {
left: 48px;
top: 65px;
font-size: 1.6rem;
}
}

@media screen and (max-width: 389px) {
div {
/* iPhone SE */
max-width: 252px;
}
}

/* Desktop */
@media screen and (min-width: 701px) {
div {
left: 394px;
top: 10px;
height: 44px;
display: flex;
align-items: center;
}
}
</style>
2 changes: 1 addition & 1 deletion src/lib/components/Nav/Mobile/MobileNav.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
</nav>

<style>
@media screen and (min-width: 700px) {
@media screen and (min-width: 701px) {
nav {
display: none;
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/UI/Avatar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
}
}

@media (min-width: 700px) and (max-width: 850px) {
@media (min-width: 701px) and (max-width: 850px) {
.avatar:not(.large) {
width: 4rem;
height: 4rem;
Expand Down
7 changes: 7 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,10 @@ export const ICON_SIZE = [
];

export const IMAGES_PATH = '/images';

/**
* MapBox max zoom level for non-members, in order to preserve privacy
*/
export const nonMemberMaxZoom = 12;
// This is the MapBox default https://docs.mapbox.com/mapbox-gl-js/api/map/#map-parameters
export const memberMaxZoom = 22;
3 changes: 2 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,8 @@
"drag-here": "Drag here or {selectFile}",
"select-file": "select file",
"added-to-map": "has been added to the map."
}
},
"zoom-restriction-notice": "to zoom in more"
},
"terms-of-use": {
"title": "Terms of use",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,8 @@
"drag-here": "Faites glisser ici ou {selectFile}",
"select-file": "sélectionnez le fichier",
"added-to-map": "a été ajouté sur la carte."
}
},
"zoom-restriction-notice": "pour zoomer plus"
},
"terms-of-use": {
"title": "Conditions d'utilisation",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,8 @@
"drag-here": "Sleep hier of {selectFile}",
"select-file": "selecteer een bestand",
"added-to-map": "is toegevoegd aan de kaart."
}
},
"zoom-restriction-notice": "om meer in te zoomen"
},
"rules": {
"title": "Regels",
Expand Down
2 changes: 1 addition & 1 deletion src/routes/chat/[name]/[chatId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ CSS grids should do the job cleanly -->
padding: 1.7rem;
}

@media (min-width: 700px) and (max-width: 850px) {
@media (min-width: 701px) and (max-width: 850px) {
.message {
max-width: 80%;
}
Expand Down
2 changes: 2 additions & 0 deletions src/routes/explore/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import trackEvent from '$lib/util/track-plausible';
import { PlausibleEvent } from '$lib/types/Plausible';
import { setExpiringCookie } from '$lib/util/set-cookie';
import ZoomRestrictionNotice from '$lib/components/Map/ZoomRestrictionNotice.svelte';

let fallbackLocation = { longitude: 4.5, latitude: 50.5 };
let geolocationIsLoaded = false;
Expand Down Expand Up @@ -178,6 +179,7 @@
{/if}
<FileTrails />
<TrainconnectionsLayer />
<ZoomRestrictionNotice />
</Map>
<LayersAndTools
bind:showHiking
Expand Down