Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Commit

Permalink
Museum (#193)
Browse files Browse the repository at this point in the history
* Overlay with list & Camera movement WIP

* Dropy marker & Overlay done

* Data link with new route

* Fix

* Fix app.json

* Fix

* Requested changes
  • Loading branch information
celian-rib authored Sep 5, 2022
1 parent 51683f4 commit 0a9f045
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 161 deletions.
78 changes: 70 additions & 8 deletions src/components/DropyMap.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { StyleSheet, Platform } from 'react-native';

import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
import LinearGradient from 'react-native-linear-gradient';

import { useNavigation } from '@react-navigation/native';
import { useInitializedGeolocation } from '../hooks/useGeolocation';
import useMapViewSyncronizer, { INITIAL_PITCH, INITIAL_ZOOM } from '../hooks/useMapViewSyncronizer';
import useOverlay from '../hooks/useOverlay';

import mapStyleAndroid from '../assets/mapStyleAndroid.json';
Expand All @@ -15,12 +14,18 @@ import mapStyleIOS from '../assets/mapStyleIOS.json';
import API from '../services/API';
import Haptics from '../utils/haptics';

import { coordinatesDistance } from '../utils/coordinates';
import MapLoadingOverlay from './overlays/MapLoadingOverlay';
import Sonar from './Sonar';
import DropyMapMarker from './DropyMapMarker';
import DebugText from './DebugText';
import RetrievedDropyMapMarker from './RetrievedDropyMapMarker';

const DropyMap = ({ dropiesAround, retrieveDropy }) => {
const INITIAL_PITCH = 10;
const INITIAL_ZOOM = 17;
const MUSEUM_ZOOM = 13;

const DropyMap = ({ dropiesAround, retrieveDropy, museumVisible, selectedDropyIndex = null, retrievedDropies = null }) => {

const navigation = useNavigation();

Expand Down Expand Up @@ -53,8 +58,48 @@ const DropyMap = ({ dropiesAround, retrieveDropy }) => {
};

const mapRef = useRef(null);

const [mapIsReady, setMapIsReady] = useState(false);
useMapViewSyncronizer(mapRef, mapIsReady);

useEffect(() => {
if(mapIsReady === false) return;
if(mapRef?.current == null) return;
if (userCoordinates == null) return;

setMapCameraPosition();
}, [userCoordinates, compassHeading, mapIsReady, selectedDropyIndex, retrievedDropies]);

const setMapCameraPosition = async () => {
const currentCamera = await mapRef.current?.getCamera();
if (currentCamera == null) return;

let position = userCoordinates;
if(retrievedDropies != null && selectedDropyIndex != null && retrievedDropies[selectedDropyIndex] != null) {
position = {
latitude: retrievedDropies[selectedDropyIndex].latitude,
longitude: retrievedDropies[selectedDropyIndex].longitude,
};
}

const distanceBetweenCameraAndPosition = coordinatesDistance(currentCamera.center, position);
const duration = 2000 - Math.min(distanceBetweenCameraAndPosition, 1500);

// eslint-disable-next-line no-undef
requestAnimationFrame(() => {
mapRef.current.animateCamera(
{
center: {
latitude: position.latitude,
longitude: position.longitude,
},
pitch: museumVisible ? 45 : INITIAL_PITCH,
heading: compassHeading,
zoom: museumVisible ? MUSEUM_ZOOM : INITIAL_ZOOM,
},
{ duration: museumVisible ? 500 : duration }
);
});
};

return (
<>
Expand All @@ -80,11 +125,28 @@ const DropyMap = ({ dropiesAround, retrieveDropy }) => {
}}
onMapLoaded={() => setMapIsReady(true)}
>
{dropiesAround.map((dropy) => (
<DropyMapMarker key={dropy.id} dropy={dropy} onPress={() => handleDropyPressed(dropy)} />
))}
{retrievedDropies != null ? (
<>
{retrievedDropies[selectedDropyIndex ?? 0] != null && (
<RetrievedDropyMapMarker
key={retrievedDropies[selectedDropyIndex ?? 0].id}
dropy={retrievedDropies[selectedDropyIndex ?? 0]}
onPress={() => navigation.navigate('DisplayDropyMedia', {
dropy: retrievedDropies[selectedDropyIndex ?? 0],
showBottomModal: false,
})}
/>
)}
</>
) : (
<>
{dropiesAround.map((dropy) => (
<DropyMapMarker key={dropy.id} dropy={dropy} onPress={() => handleDropyPressed(dropy)} />
))}
</>
)}
</MapView>
<Sonar />
<Sonar visible={!museumVisible} />
<MapLoadingOverlay visible={geolocationInitialized === false} />
<LinearGradient
pointerEvents='none'
Expand Down
6 changes: 3 additions & 3 deletions src/components/FooterConfirmation.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ const FooterConfirmation = ({ dropy, onPress, textButton }) => {
width={65}
height={65}
resizeMode="cover"
avatarUrl={dropy.emitterAvatarUrl}
displayName={dropy.emitterDisplayName}
avatarUrl={dropy.emitter.avatarUrl}
displayName={dropy.emitter.displayName}
/>
</View>
<View style={styles.infoDropy}>
<Text style={styles.profileName}>@{dropy.emitterDisplayName}</Text>
<Text style={styles.profileName}>@{dropy.emitter.displayName}</Text>
<Text style={styles.dropyDate}>Dropped here {createDropTimeString(new Date() - new Date(dropy.creationDate))} ago</Text>
</View>
</View>
Expand Down
143 changes: 116 additions & 27 deletions src/components/HomeScreenTabBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,25 @@ import GlassCircleButton from './GlassCircleButton';
const mainButtonSize = responsiveHeight(7.5);
const iconsSize = 30;

const HomeScreenTabBar = () => {
const HomeScreenTabBar = ({ onMuseumOpenPressed, onMuseumClosePressed, museumVisible }) => {
const navigation = useNavigation();

const tabBarAnimatedValue = useRef(new Animated.Value(0)).current;
const mainButtonAnimatedValue = useRef(new Animated.Value(0)).current;
const wheelAnimatedValue = useRef(new Animated.Value(0)).current;

const [dropyMenuIsOpen, setDropyMenuIsOpen] = useState(false);
const [renderMenuOverlay, setRenderMenuOverlay] = useState(false);
const [renderMuseumCloseButton, setRenderMuseumCloseButton] = useState(false);

const hasUnreadConversation = useUnreadConversation();

const { sendAlert } = useOverlay();

const menuAnimatedValue = useRef(new Animated.Value(0)).current;
useEffect(() => {
Haptics.impactLight();
setRenderMenuOverlay(true);
const anim = Animated.timing(menuAnimatedValue, {
const anim = Animated.timing(wheelAnimatedValue, {
toValue: dropyMenuIsOpen ? 1 : 0,
duration: 300,
useNativeDriver: true,
Expand All @@ -50,11 +54,58 @@ const HomeScreenTabBar = () => {
return anim.stop;
}, [dropyMenuIsOpen]);

const plusIconRotation = menuAnimatedValue.interpolate({
useEffect(() => {
Haptics.impactLight();
const anim = Animated.timing(tabBarAnimatedValue, {
toValue: museumVisible ? 1 : 0,
duration: 300,
useNativeDriver: true,
});
anim.start();
return anim.stop;
}, [museumVisible]);

useEffect(() => {
Haptics.impactLight();
setRenderMuseumCloseButton(true);
const anim = Animated.timing(mainButtonAnimatedValue, {
toValue: museumVisible ? 1 : 0,
duration: 400,
useNativeDriver: true,
easing: Easing.elastic(1.1),
});
anim.start(({ finished }) => {
if (finished && !museumVisible)
setRenderMuseumCloseButton(false);
});
return anim.stop;
}, [museumVisible]);

const plusIconRotation = wheelAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '45deg'],
});

const tabBarTranslateY = tabBarAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, responsiveHeight(20)],
});

const glassButtonOpacity = tabBarAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
});

const glassButtonScale = mainButtonAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0.5],
});

const museumCloseButtonScale = mainButtonAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0.5, 1],
});

const handleAddPicture = () => {
navigation.navigate('CreateDropyFromLibrary');
setDropyMenuIsOpen(false);
Expand All @@ -81,17 +132,27 @@ const HomeScreenTabBar = () => {

return (
<View style={styles.container}>
<Svg
height="100%"
width={responsiveWidth(100)}
viewBox="0 0 375 87"
style={styles.backgroundSvg}
preserveAspectRatio="none"
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
transform: [{ translateY :tabBarTranslateY }],
}}
>
<Path d={d} fill="white" />
</Svg>
<View style={styles.tabsContainer}>
<TabBarItem text="Drops">
<Svg
height="100%"
width={responsiveWidth(100)}
viewBox="0 0 375 87"
style={styles.backgroundSvg}
preserveAspectRatio="none"
>
<Path d={d} fill="white" />
</Svg>
</Animated.View>
<Animated.View style={{
...styles.tabsContainer,
transform: [{ translateY :tabBarTranslateY }],
}}>
<TabBarItem text="Drops" onPress={onMuseumOpenPressed}>
<Ionicons
name="md-bookmark-outline"
size={iconsSize}
Expand All @@ -106,13 +167,13 @@ const HomeScreenTabBar = () => {
style={styles.icons}
/>
</TabBarItem>
</View>
</Animated.View>
{renderMenuOverlay && (
<>
<TouchableOpacity style={StyleSheet.absoluteFillObject} activeOpacity={1} onPress={() => setDropyMenuIsOpen(false)}>
<Animated.View style={{ ...styles.backgroundOverlay, opacity: menuAnimatedValue }} />
<Animated.View style={{ ...styles.backgroundOverlay, opacity: wheelAnimatedValue }} />
</TouchableOpacity>
<DropyWheel isOpen={dropyMenuIsOpen} menuAnimatedValue={menuAnimatedValue}>
<DropyWheel isOpen={dropyMenuIsOpen} menuAnimatedValue={wheelAnimatedValue}>
<TouchableOpacity style={styles.dropySelectionButton} onPress={handleAddPicture}>
<SimpleLineIcons name="picture" size={30} color={Colors.grey} />
</TouchableOpacity>
Expand All @@ -128,15 +189,35 @@ const HomeScreenTabBar = () => {
</DropyWheel>
</>
)}
<GlassCircleButton
style={styles.mainButton}
size={mainButtonSize}
onPress={() => setDropyMenuIsOpen(!dropyMenuIsOpen)}
>
<Animated.View style={{ transform: [{ rotate: plusIconRotation }] }}>
<FontAwesome5 name="plus" size={20} color="white" />

<Animated.View style={{
...styles.mainButton,
opacity: glassButtonOpacity,
transform: [{ scale: glassButtonScale }],
}}>
<GlassCircleButton
size={mainButtonSize}
onPress={() => setDropyMenuIsOpen(!dropyMenuIsOpen)}
>
<Animated.View style={{ transform: [{ rotate: plusIconRotation }] }}>
<FontAwesome5 name="plus" size={20} color="white" />
</Animated.View>
</GlassCircleButton>
</Animated.View>

{renderMuseumCloseButton && (
<Animated.View style={{
...styles.mainButton,
opacity: tabBarAnimatedValue,
transform: [{ scale: museumCloseButtonScale }],
}}>
<TouchableOpacity onPress={onMuseumClosePressed} style={styles.closeMuseumButton}>
<View style={{ transform: [{ rotate: '45deg' }] }}>
<FontAwesome5 name="plus" size={20} color={Colors.darkGrey} />
</View>
</TouchableOpacity>
</Animated.View>
</GlassCircleButton>
)}
</View>
);
};
Expand Down Expand Up @@ -177,7 +258,7 @@ const DropyWheelItem = ({ children, index, childCount, size }) => {
);
};

const TabBarItem = ({ children, text, showStatusDot, routeName }) => {
const TabBarItem = ({ children, text, showStatusDot, routeName, onPress }) => {

const { sendAlert } = useOverlay();
const navigation = useNavigation();
Expand All @@ -195,7 +276,7 @@ const TabBarItem = ({ children, text, showStatusDot, routeName }) => {
};

return (
<TouchableOpacity style={styles.tabBtn} onPress={goToRoute}>
<TouchableOpacity style={styles.tabBtn} onPress={onPress ?? goToRoute}>
{children}
{showStatusDot && <View style={styles.statusDot} />}
<Text style={styles.tabText}>{text}</Text>
Expand Down Expand Up @@ -274,6 +355,14 @@ const styles = StyleSheet.create({
...Styles.center,
...Styles.hardShadows,
},
closeMuseumButton: {
backgroundColor: Colors.white,
width: mainButtonSize,
height: mainButtonSize,
borderRadius: mainButtonSize,
...Styles.center,
...Styles.softShadows,
},
});

const d = 'M 0 28 C 0 12.535995 12.535999 0 28 0 L 101.5 0 L 135.268005 0 C 143.283005 0 150.514999 4.8116 153.612 12.204597 L 154.119995 13.417099 C 166.593002 43.1978 208.985992 42.625 220.649994 12.518097 L 220.649994 12.518097 C 223.572998 4.9729 230.832993 0 238.924988 0 L 273.5 0 L 347 0 C 362.463989 0 375 12.535995 375 28 L 375 87 L 0 87 L 0 28 Z';
Loading

0 comments on commit 0a9f045

Please sign in to comment.