bottom tab

This commit is contained in:
2025-09-30 10:26:36 +02:00
parent 542fa23a98
commit 27fab69997
3 changed files with 85 additions and 89 deletions
+11 -24
View File
@@ -1,34 +1,20 @@
import React, { useGlobal } from "reactn";
import { StyleSheet } from "react-native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Motion } from "@legendapp/motion"; import { Motion } from "@legendapp/motion";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import React from "reactn";
import { responsiveHeight } from "../actions/responsiveSizes.js";
import useLayoutType from "../hooks/useLayoutType.js";
import { Routes } from "./Routes";
import { Palette } from "../styles"; import { Palette } from "../styles";
import { Routes } from "./Routes";
import { tabs } from "../assets"; import { tabs } from "../assets";
import TabBar from "./TabBar"; import TabBar from "./TabBar";
import HomeStack from "./HomeStack"; import { Platform } from "react-native";
import ChatStack from "./ChatStack";
import SettingsStack from "./SettingsStack";
import Library from "../screens/Library/Library.js";
import Profile from "../screens/Profile/Profile.js";
import HitParade from "../screens/HitParade/HitParade.js"; import HitParade from "../screens/HitParade/HitParade.js";
import Library from "../screens/Library/Library.js";
import Playbacks from "../screens/Playbacks.js"; import Playbacks from "../screens/Playbacks.js";
import Profile from "../screens/Profile/Profile.js";
const bottomTabStyles = StyleSheet.create({ import HomeStack from "./HomeStack";
icon: {
width: responsiveHeight(5),
height: responsiveHeight(5),
resizeMode: "contain",
},
});
const BottomTab = createBottomTabNavigator(); const BottomTab = createBottomTabNavigator();
@@ -40,10 +26,11 @@ export const BottomTabScreen = () => {
tintColor: focused ? Palette.white : "#8B8883", tintColor: focused ? Palette.white : "#8B8883",
}} }}
style={[ style={[
bottomTabStyles.icon,
{ {
width: 24, width: Platform.OS === "web" ? 30 : 24,
height: 24, height: Platform.OS === "web" ? 30 : 24,
marginBottom: Platform.OS === "web" ? 13 : 0,
marginTop: Platform.OS === "web" ? 13 : 0,
}, },
]} ]}
source={icon} source={icon}
+6 -9
View File
@@ -1,13 +1,10 @@
import React from "react";
import { View, TouchableOpacity, Text } from "react-native";
import * as Haptics from "expo-haptics"; import * as Haptics from "expo-haptics";
import React from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { gutters, Palette, Style } from "../styles";
import useLayoutType from "../hooks/useLayoutType";
import BorderGradient from "../components/BorderGradient/BorderGradient";
import { colors } from "react-native-swiper-flatlist/src/themes";
import { BlurView } from "expo-blur";
import ItemContainer from "../components/ItemContainer/ItemContainer"; import ItemContainer from "../components/ItemContainer/ItemContainer";
import useLayoutType from "../hooks/useLayoutType";
import { gutters, Palette, Style } from "../styles";
import { FONT_FAMILY } from "../styles/Fonts"; import { FONT_FAMILY } from "../styles/Fonts";
const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => { const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
@@ -32,7 +29,7 @@ const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
end: { x: 1, y: 0 }, end: { x: 1, y: 0 },
}} }}
style={{ style={{
height: 65, height: isWeb ? 80 : 65,
}} }}
> >
<View <View
@@ -97,7 +94,7 @@ const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
{options?.tabBarIcon({ focused: isFocused })} {options?.tabBarIcon({ focused: isFocused })}
<Text <Text
style={{ style={{
fontSize: 10, fontSize: isWeb ? 14 : 10,
color: isFocused ? Palette.white : "#8B8883", color: isFocused ? Palette.white : "#8B8883",
fontFamily: FONT_FAMILY.HelveticaNeueRegular, fontFamily: FONT_FAMILY.HelveticaNeueRegular,
marginTop: 2, marginTop: 2,
+66 -54
View File
@@ -1,33 +1,33 @@
import { useIsFocused, useRoute } from '@react-navigation/native'; import { useIsFocused, useRoute } from "@react-navigation/native";
import { useAudioPlayer } from 'expo-audio'; import { useAudioPlayer } from "expo-audio";
import { BlurView } from 'expo-blur'; import { BlurView } from "expo-blur";
import { VideoView, useVideoPlayer } from 'expo-video'; import { VideoView, useVideoPlayer } from "expo-video";
import React, { import React, {
useCallback, useCallback,
useEffect, useEffect,
useMemo, useMemo,
useRef, useRef,
useState, useState,
} from 'react'; } from "react";
import { Image, Platform, Pressable, Share, Text, View } from 'react-native'; import { Image, Platform, Pressable, Share, Text, View } from "react-native";
import Carousel from 'react-native-reanimated-carousel'; import Carousel from "react-native-reanimated-carousel";
import { responsiveHeight } from 'react-native-responsive-dimensions'; import { responsiveHeight } from "react-native-responsive-dimensions";
import { icons, img } from '../assets'; import { icons, img } from "../assets";
import { openComments } from '../components/bottomsheets/CommentsBottomSheet'; import { openComments } from "../components/bottomsheets/CommentsBottomSheet";
import KaraokeLyrics from '../components/KaraokeLyrics'; import KaraokeLyrics from "../components/KaraokeLyrics";
import { import {
arrayRemove, arrayRemove,
arrayUnion, arrayUnion,
projectsRef, projectsRef,
usersRef, usersRef,
} from '../config/firebase'; } from "../config/firebase";
import useDataFromRef from '../hooks/useDataFromRef'; import useDataFromRef from "../hooks/useDataFromRef";
import { Routes } from '../navigation'; import { Routes } from "../navigation";
import { navigate } from '../navigation/NavigationService'; import { navigate } from "../navigation/NavigationService";
import { useUser } from '../providers/UserDataProvider'; import { useUser } from "../providers/UserDataProvider";
import { Palette } from '../styles'; import { Palette } from "../styles";
import { FONT_FAMILY } from '../styles/Fonts'; import { FONT_FAMILY } from "../styles/Fonts";
import { size } from '../styles/Style'; import { size } from "../styles/Style";
const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
const { currentUID, followUser, unfollowUser } = useUser() || {}; const { currentUID, followUser, unfollowUser } = useUser() || {};
@@ -176,7 +176,7 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : []; const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [];
return arr.map((w) => ({ return arr.map((w) => ({
word: String(w?.word ?? ''), word: String(w?.word ?? ""),
startS: Number(w?.startS ?? 0), startS: Number(w?.startS ?? 0),
endS: Number(w?.endS ?? 0), endS: Number(w?.endS ?? 0),
})); }));
@@ -202,43 +202,47 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
<View <View
style={{ style={{
height: responsiveHeight(100), height: responsiveHeight(100),
position: 'relative', position: "relative",
backgroundColor: 'black', backgroundColor: "black",
}}> }}
>
{!!videoUrl ? ( {!!videoUrl ? (
<VideoView <VideoView
player={videoPlayer} player={videoPlayer}
nativeControls={false} nativeControls={false}
contentFit="cover" contentFit="cover"
style={{ width: '100%', height: '100%' }} style={{ width: "100%", height: "100%" }}
/> />
) : ( ) : (
<Image <Image
source={img.placeholder3} source={img.placeholder3}
style={{ width: '100%', height: '100%' }} style={{ width: "100%", height: "100%" }}
/> />
)} )}
{/* Right side actions */} {/* Right side actions */}
<View <View
style={{ style={{
position: 'absolute', position: "absolute",
width: '100%', width: "100%",
bottom: 130, bottom: 130,
gap: 18, gap: 18,
}}> }}
>
<View <View
style={{ style={{
alignSelf: 'flex-end', alignSelf: "flex-end",
alignItems: 'center', alignItems: "center",
gap: 20, gap: 20,
paddingHorizontal: 13, paddingHorizontal: 13,
}}> }}
<View style={{ gap: 6, alignItems: 'center' }}> >
<View style={{ gap: 6, alignItems: "center" }}>
<Pressable <Pressable
onPress={() => { onPress={() => {
navigate(Routes.SingerProfile, { userId: item?.userId }); navigate(Routes.SingerProfile, { userId: item?.userId });
}}> }}
>
{owner?.profilePictureURL ? ( {owner?.profilePictureURL ? (
<Image <Image
source={{ uri: owner.profilePictureURL }} source={{ uri: owner.profilePictureURL }}
@@ -279,18 +283,19 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
// rollback on failure // rollback on failure
setIsFollowing((v) => !v); setIsFollowing((v) => !v);
} }
}}> }}
>
<BlurView <BlurView
tint="dark" tint="dark"
intensity={Platform.OS !== 'ios' ? 10 : 20} intensity={Platform.OS !== "ios" ? 10 : 20}
style={{ style={{
paddingVertical: 6, paddingVertical: 6,
paddingHorizontal: 12, paddingHorizontal: 12,
borderRadius: 12, borderRadius: 12,
borderWidth: 1, borderWidth: 1,
borderColor: Palette.white, borderColor: Palette.white,
overflow: 'hidden', overflow: "hidden",
backgroundColor: isFollowing ? '#FFFFFF1A' : undefined, backgroundColor: isFollowing ? "#FFFFFF1A" : undefined,
}} }}
// experimentalBlurMethod={ // experimentalBlurMethod={
// Platform.OS !== "ios" ? "dimezisBlurView" : "none" // Platform.OS !== "ios" ? "dimezisBlurView" : "none"
@@ -301,8 +306,9 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
fontSize: 13, fontSize: 13,
color: Palette.white, color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium, fontFamily: FONT_FAMILY.InterMedium,
}}> }}
{isFollowing ? 'Ne plus suivre' : 'Suivre'} >
{isFollowing ? "Ne plus suivre" : "Suivre"}
</Text> </Text>
</BlurView> </BlurView>
</Pressable> </Pressable>
@@ -332,7 +338,8 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
setLikesCount((c) => (isLiked ? c + 1 : Math.max(0, c - 1))); setLikesCount((c) => (isLiked ? c + 1 : Math.max(0, c - 1)));
} }
}} }}
style={{ alignItems: 'center' }}> style={{ alignItems: "center" }}
>
<Image <Image
source={isLiked ? icons.heart : icons.heartOutline} source={isLiked ? icons.heart : icons.heartOutline}
style={size({ size: 26 })} style={size({ size: 26 })}
@@ -345,15 +352,17 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
fontSize: 11, fontSize: 11,
marginTop: 4, marginTop: 4,
fontFamily: FONT_FAMILY.InterMedium, fontFamily: FONT_FAMILY.InterMedium,
textAlign: 'center', textAlign: "center",
}}> }}
>
{likesCount} {likesCount}
</Text> </Text>
)} )}
</Pressable> </Pressable>
<Pressable <Pressable
onPress={() => item?.id && openComments(item.id)} onPress={() => item?.id && openComments(item.id)}
style={{ alignItems: 'center' }}> style={{ alignItems: "center" }}
>
<Image source={icons.chatBubble} style={size({ size: 26 })} /> <Image source={icons.chatBubble} style={size({ size: 26 })} />
{!!commentsCount && ( {!!commentsCount && (
<Text <Text
@@ -362,8 +371,9 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
fontSize: 11, fontSize: 11,
marginTop: 4, marginTop: 4,
fontFamily: FONT_FAMILY.InterMedium, fontFamily: FONT_FAMILY.InterMedium,
textAlign: 'center', textAlign: "center",
}}> }}
>
{commentsCount} {commentsCount}
</Text> </Text>
)} )}
@@ -371,8 +381,8 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
<Pressable <Pressable
onPress={async () => { onPress={async () => {
try { try {
const url = item?.playbackUrl || ''; const url = item?.playbackUrl || "";
const title = item?.title || 'Partager'; const title = item?.title || "Partager";
const base = item?.title const base = item?.title
? `Découvre « ${item.title} » sur MusicLand` ? `Découvre « ${item.title} » sur MusicLand`
: `Découvre ce playback sur MusicLand`; : `Découvre ce playback sur MusicLand`;
@@ -385,20 +395,21 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
}) })
); );
} catch (e) {} } catch (e) {}
}}> }}
>
<Image source={icons.share} style={size({ size: 26 })} /> <Image source={icons.share} style={size({ size: 26 })} />
</Pressable> </Pressable>
</View> </View>
<View style={{ paddingHorizontal: 28 }}> <View style={{ paddingHorizontal: 28 }}>
<BlurView <BlurView
tint="dark" tint="dark"
intensity={Platform.OS !== 'ios' ? 10 : 20} intensity={Platform.OS !== "ios" ? 10 : 20}
style={{ style={{
paddingHorizontal: 14, paddingHorizontal: 14,
paddingVertical: 8, paddingVertical: 8,
borderRadius: 20, borderRadius: 20,
backgroundColor: Palette.glass, backgroundColor: Palette.glass,
overflow: 'hidden', overflow: "hidden",
}} }}
// experimentalBlurMethod={ // experimentalBlurMethod={
// Platform.OS !== "ios" ? "dimezisBlurView" : "none" // Platform.OS !== "ios" ? "dimezisBlurView" : "none"
@@ -415,8 +426,9 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
fontSize: 12, fontSize: 12,
color: Palette.white, color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular, fontFamily: FONT_FAMILY.InterRegular,
}}> }}
{item?.title || 'Description chanson'} >
{item?.title || "Description chanson"}
</Text> </Text>
)} )}
</BlurView> </BlurView>
@@ -436,7 +448,7 @@ const Playbacks = () => {
const { getUserByUid } = useUser() || {}; const { getUserByUid } = useUser() || {};
const isFocused = useIsFocused(); const isFocused = useIsFocused();
const { data: playbacks = [], loadMore } = useDataFromRef({ const { data: playbacks = [], loadMore } = useDataFromRef({
ref: projectsRef.where('playbackUrl', '!=', null), ref: projectsRef.where("playbackUrl", "!=", null),
simpleRef: false, simpleRef: false,
listener: false, listener: false,
usePagination: true, usePagination: true,
@@ -475,7 +487,7 @@ const Playbacks = () => {
}, [focusProjectId, playbacks, loadMore]); }, [focusProjectId, playbacks, loadMore]);
return ( return (
<View style={{ flex: 1, backgroundColor: 'black' }}> <View style={{ flex: 1, backgroundColor: "black" }}>
<Carousel <Carousel
ref={carouselRef} ref={carouselRef}
data={playbacks} data={playbacks}