diff --git a/src/components/Home/AccountSwitcher.tsx b/src/components/Home/AccountSwitcher.tsx index 496f83b4c..5f1d26ca3 100644 --- a/src/components/Home/AccountSwitcher.tsx +++ b/src/components/Home/AccountSwitcher.tsx @@ -15,13 +15,15 @@ import { defaultProfilePicture } from "@/utils/ui/default-profile-picture"; import PapillonSpinner from "../Global/PapillonSpinner"; import { animPapillon } from "@/utils/ui/animations"; import Animated from "react-native-reanimated"; +import { BlurView } from "expo-blur"; const AccountSwitcher: React.FC<{ small?: boolean, - scrolled?: boolean, + opened?: boolean, + modalOpen?: boolean, translationY?: Reanimated.SharedValue, loading?: boolean, -}> = ({ small, translationY, loading }) => { +}> = ({ small, opened, modalOpen, translationY, loading }) => { const theme = useTheme(); const { colors } = theme; @@ -68,87 +70,117 @@ const AccountSwitcher: React.FC<{ })); return ( - - + - {!shouldHidePicture ? ( - - ) : ( - - )} - - - {account.studentName ? ( - account.studentName?.first + (shouldHideName ? "" : " " + account.studentName.last) - ) : "Mon compte"} - - - {loading && ( - - )} - - + {!shouldHidePicture ? ( + + ) : ( + + )} + + + {account.studentName ? ( + account.studentName?.first + (shouldHideName ? "" : " " + account.studentName.last) + ) : "Mon compte"} + + + {loading && ( + + )} + + + + - + ); }; @@ -165,14 +197,6 @@ const styles = StyleSheet.create({ overflow: "hidden", paddingVertical: 6, gap: 6, - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 1, - }, - shadowOpacity: 0.15, - shadowRadius: 3, - elevation: 3, }, avatar: { @@ -180,6 +204,8 @@ const styles = StyleSheet.create({ aspectRatio: 1, borderRadius: 24, backgroundColor: "#00000010", + borderColor: "#00000020", + borderWidth: 1, }, accountSwitcherText: { diff --git a/src/components/Home/AccountSwitcherContextMenu.tsx b/src/components/Home/AccountSwitcherContextMenu.tsx index 026ef408c..16cc7ccd8 100644 --- a/src/components/Home/AccountSwitcherContextMenu.tsx +++ b/src/components/Home/AccountSwitcherContextMenu.tsx @@ -79,7 +79,9 @@ const ContextMenu: React.FC<{ elevation: opened ? 3 : 0, }} > - {children} + {React.cloneElement(children as React.ReactElement, { + opened, + })} ) : ( - {children} + {React.cloneElement(children as React.ReactElement, { + opened, + })} )} diff --git a/src/components/Home/Header.tsx b/src/components/Home/Header.tsx index eff05ebac..17e2226f7 100644 --- a/src/components/Home/Header.tsx +++ b/src/components/Home/Header.tsx @@ -240,6 +240,7 @@ const Header: React.FC<{ style={{ gap: 15, flexDirection: "row", + height: 131, }} > {Widgets.map((widget, index) => ( diff --git a/src/views/account/Home/Home.tsx b/src/views/account/Home/Home.tsx index d47fa2c39..0b78cffe5 100644 --- a/src/views/account/Home/Home.tsx +++ b/src/views/account/Home/Home.tsx @@ -35,11 +35,12 @@ import {protectScreenComponent} from "@/router/helpers/protected-screen"; import type {Screen} from "@/router/helpers/types"; import {useCurrentAccount} from "@/stores/account"; import getCorners from "@/utils/ui/corner-radius"; -import {useTheme} from "@react-navigation/native"; +import {useIsFocused, useTheme} from "@react-navigation/native"; import React, {useCallback, useMemo, useState} from "react"; import { Dimensions, RefreshControl, + StatusBar, View } from "react-native"; import Reanimated from "react-native-reanimated"; @@ -62,6 +63,7 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { const { colors } = useTheme(); const insets = useSafeAreaInsets(); const corners = useMemo(() => getCorners(), []); + const focused = useIsFocused(); let scrollRef = useAnimatedRef(); let scrollOffset = useScrollViewOffset(scrollRef); @@ -106,14 +108,14 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { borderCurve: "continuous", borderTopLeftRadius: interpolate( scrollOffset.value, - [0, 265 + insets.top], - [20, corners], + [0, 265 + insets.top - 1, 265 + insets.top], + [12, corners, 0], Extrapolation.CLAMP ), borderTopRightRadius: interpolate( scrollOffset.value, - [0, 265 + insets.top], - [20, corners], + [0, 265 + insets.top - 1, 265 + insets.top], + [12, corners, 0], Extrapolation.CLAMP ), @@ -130,10 +132,10 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { backgroundColor: colors.card, overflow: "hidden", transform: [ - { scaleX: interpolate( + {scale: interpolate( scrollOffset.value, - [0, 125, 265], - [1, 0.95, 1], + [0, 100, 200, 260 + insets.top], + [1, 0.95, 0.95, 1], Extrapolation.CLAMP )}, {translateY: interpolate( @@ -147,7 +149,7 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { const navigationBarAnimatedStyle = useAnimatedStyle(() => ({ position: "absolute", - top: scrollOffset.value - 265 - insets.top, + top: scrollOffset.value - 270 - insets.top, left: 0, right: 0, height: interpolate( @@ -214,6 +216,9 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { return ( + {!modalOpen && focused && ( + + )} = ({ navigation }) => { > @@ -236,6 +242,7 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { style={scrollViewAnimatedStyle} snapToOffsets={[0, 265 + insets.top]} decelerationRate={modalOpen ? "normal" : 0} + scrollEventThrottle={16} onScrollEndDrag={(e) => { if (e.nativeEvent.contentOffset.y < 265 + insets.top && modalOpen) { scrollRef.current?.scrollTo({ y: 0, animated: true }); @@ -248,9 +255,8 @@ const Home: Screen<"HomeScreen"> = ({ navigation }) => { } else if (e.nativeEvent.contentOffset.y < 125 && !canHaptics) { setCanHaptics(true); } - }} - onMomentumScrollEnd={(e) => { - setModalOpen(e.nativeEvent.contentOffset.y >= 265 + insets.top); + + setModalOpen(e.nativeEvent.contentOffset.y >= 195 + insets.top); }} refreshControl={ = ({ navigation }) => { - diff --git a/src/views/account/Home/ModalContent.tsx b/src/views/account/Home/ModalContent.tsx index e025c0102..d009e3556 100644 --- a/src/views/account/Home/ModalContent.tsx +++ b/src/views/account/Home/ModalContent.tsx @@ -10,7 +10,7 @@ import Reanimated, { import {Gift, WifiOff} from "lucide-react-native"; import {useTheme} from "@react-navigation/native"; import PackageJSON from "../../../../package.json"; -import {View} from "react-native"; +import {Dimensions, View} from "react-native"; import NetInfo from "@react-native-community/netinfo"; import {getErrorTitle} from "@/utils/format/get_papillon_error_title"; @@ -132,7 +132,11 @@ const ModalContent = ({ navigation, refresh, endRefresh }) => { }, []); return ( - + {(defined("force_changelog") || updatedRecently) && (