Skip to content

Commit

Permalink
feat: send mobile-app param to map (#1202)
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia authored May 1, 2024
1 parent 49f47cc commit c041a99
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 458 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@graasp/chatbox": "3.1.0",
"@graasp/map": "1.11.0",
"@graasp/map": "1.11.1",
"@graasp/query-client": "3.5.0",
"@graasp/sdk": "4.7.6",
"@graasp/translations": "1.27.0",
Expand Down
100 changes: 73 additions & 27 deletions src/components/item/MapView.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,74 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';

import { Stack, Typography } from '@mui/material';
import { Skeleton, Stack, Typography } from '@mui/material';

import { Map } from '@graasp/map';
import { type DiscriminatedItem, ItemGeolocation, redirect } from '@graasp/sdk';
import { type DiscriminatedItem, ItemGeolocation } from '@graasp/sdk';
import { useMobileView } from '@graasp/ui';

import { buildGraaspPlayerView } from '@/config/externalPaths';
import { hooks, mutations } from '@/config/queryClient';
import { buildPlayerTabName } from '@/config/selectors';

import NewItemModal from '../main/NewItemModal';

type Props = {
parentId?: DiscriminatedItem['id'];
title?: string;
height?: string;
viewItem: (item: DiscriminatedItem) => void;
enableGeolocation?: boolean;
};

const MapView = ({ parentId, title, height = '100vh' }: Props): JSX.Element => {
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};

const useCurrentLocation = () => {
const [hasFetchedCurrentLocation, setHasFetchedCurrentLocation] =
useState(false);

const [currentPosition, setCurrentPosition] = useState<{
lat: number;
lng: number;
}>();

// get current location
useEffect(() => {
const success = (pos: {
coords: { latitude: number; longitude: number };
}) => {
const crd = pos.coords;
setCurrentPosition({ lat: crd.latitude, lng: crd.longitude });
setHasFetchedCurrentLocation(true);
};

navigator.geolocation.getCurrentPosition(
success,
(err: { code: number; message: string }) => {
// eslint-disable-next-line no-console
console.warn(`ERROR(${err.code}): ${err.message}`);
setHasFetchedCurrentLocation(true);
},
options,
);
}, []);

return { hasFetchedCurrentLocation, currentPosition };
};

const MapView = ({
parentId,
title,
height = '100vh',
viewItem,
enableGeolocation = true,
}: Props): JSX.Element => {
const { data: currentMember } = hooks.useCurrentMember();
const { isMobile } = useMobileView();
const [geolocation, setGeolocation] = useState<Partial<ItemGeolocation>>();
const [open, setOpen] = useState(false);
const { hasFetchedCurrentLocation, currentPosition } = useCurrentLocation();

const handleAddOnClick = (args: { location: Partial<ItemGeolocation> }) => {
setGeolocation(args.location);
Expand All @@ -45,27 +91,27 @@ const MapView = ({ parentId, title, height = '100vh' }: Props): JSX.Element => {
)}
</Stack>
<Stack flex={1}>
<div style={{ width: '100%', height: '100%' }}>
<Map
useDeleteItemGeolocation={mutations.useDeleteItemGeolocation}
usePostItem={mutations.usePostItem}
useRecycleItems={mutations.useRecycleItems}
useAddressFromGeolocation={hooks.useAddressFromGeolocation}
useSuggestionsForAddress={hooks.useSuggestionsForAddress}
useItemsInMap={hooks.useItemsInMap}
viewItem={(item) => {
redirect(window, buildGraaspPlayerView(item.id), {
name: buildPlayerTabName(item.id),
openInNewTab: true,
});
}}
currentMember={currentMember}
itemId={parentId}
// use builder modal to add new item if the screen is big enough
// todo: always use builder modal when it is responsive
handleAddOnClick={isMobile ? undefined : handleAddOnClick}
/>
</div>
{enableGeolocation && !hasFetchedCurrentLocation ? (
<Skeleton width="100%" height="100%" />
) : (
<div style={{ width: '100%', height: '100%' }}>
<Map
currentPosition={currentPosition}
useDeleteItemGeolocation={mutations.useDeleteItemGeolocation}
usePostItem={mutations.usePostItem}
useRecycleItems={mutations.useRecycleItems}
useAddressFromGeolocation={hooks.useAddressFromGeolocation}
useSuggestionsForAddress={hooks.useSuggestionsForAddress}
useItemsInMap={hooks.useItemsInMap}
viewItem={viewItem}
currentMember={currentMember}
itemId={parentId}
// use builder modal to add new item if the screen is big enough
// todo: always use builder modal when it is responsive
handleAddOnClick={isMobile ? undefined : handleAddOnClick}
/>
</div>
)}
</Stack>
</Stack>
{!isMobile && (
Expand Down
24 changes: 20 additions & 4 deletions src/components/main/Items.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { DiscriminatedItem } from '@graasp/sdk';
import { DiscriminatedItem, redirect } from '@graasp/sdk';

import { buildGraaspPlayerView } from '@/config/externalPaths';
import { buildPlayerTabName } from '@/config/selectors';
import { ShowOnlyMeChangeType } from '@/config/types';

import { hooks } from '../../config/queryClient';
Expand Down Expand Up @@ -76,9 +78,23 @@ const Items = ({
itemsTags,
});
switch (mode) {
case ItemLayoutMode.Map:
// todo: change when we deal with item screen
return <MapView title={title} parentId={parentId} height="90%" />;
case ItemLayoutMode.Map: {
const viewItem = (item: DiscriminatedItem) => {
redirect(window, buildGraaspPlayerView(item.id), {
name: buildPlayerTabName(item.id),
openInNewTab: true,
});
};

return (
<MapView
viewItem={viewItem}
title={title}
parentId={parentId}
height="90%"
/>
);
}
case ItemLayoutMode.Grid:
return (
<ItemsGrid
Expand Down
32 changes: 31 additions & 1 deletion src/components/pages/MapItemsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
import { useSearchParams } from 'react-router-dom';

import { DiscriminatedItem, redirect } from '@graasp/sdk';

import { buildGraaspPlayerView } from '@/config/externalPaths';
import { buildPlayerTabName } from '@/config/selectors';

import MapView from '../item/MapView';

// this page is used by the mobile app to display the map
const MapItemScreen = (): JSX.Element | null => {
const [urlSearchParams] = useSearchParams();

return <MapView parentId={urlSearchParams.get('parentId') ?? undefined} />;
const isMobileApp = urlSearchParams.get('isMobileApp') === 'true';
const enableGeolocation = urlSearchParams.get('enableGeolocation')
? urlSearchParams.get('enableGeolocation') === 'true'
: true;

const viewItem = (item: DiscriminatedItem) => {
if (isMobileApp) {
// todo: replace with universal/deep link? not sure it works inside iframe..
window.parent.postMessage(
JSON.stringify({ item, action: 'open-player' }),
);
} else {
redirect(window, buildGraaspPlayerView(item.id), {
name: buildPlayerTabName(item.id),
openInNewTab: true,
});
}
};

return (
<MapView
viewItem={viewItem}
enableGeolocation={enableGeolocation}
parentId={urlSearchParams.get('parentId') ?? undefined}
/>
);
};

export default MapItemScreen;
Loading

0 comments on commit c041a99

Please sign in to comment.