diff --git a/.eslintrc.js b/.eslintrc.js
index b8fbdb2..a11ee9e 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,11 +1,11 @@
module.exports = {
- extends: ['expo', 'prettier'],
- plugins: ['prettier'],
+ extends: ["expo", "prettier"],
+ plugins: ["prettier"],
rules: {
- 'prettier/prettier': [
- 'error',
+ "prettier/prettier": [
+ "error",
{
- singleQuote: true,
+ singleQuote: false,
},
],
},
diff --git a/src/layouts/AppLayout.js b/src/layouts/AppLayout.js
index 0ba57c1..99cea82 100644
--- a/src/layouts/AppLayout.js
+++ b/src/layouts/AppLayout.js
@@ -1,52 +1,51 @@
-import { View, Image } from 'react-native';
-import { useGlobal } from 'reactn';
-import { Motion } from '@legendapp/motion';
+import { Image, View } from "react-native";
+import { useGlobal } from "reactn";
-import useLayoutType from '../hooks/useLayoutType';
+import useLayoutType from "../hooks/useLayoutType";
-import Home from '../screens/Home';
-
-import { Palette, Style } from '../styles';
-import { background as backgrounds } from '../assets';
+import { background as backgrounds } from "../assets";
+import { Style } from "../styles";
export default ({ currentUID = null, children }) => {
const { isWeb = false } = useLayoutType();
// Web: full-screen background with a centered content area (30% width)
- const [webBackgroundImg] = useGlobal('webBackgroundImg');
+ const [webBackgroundImg] = useGlobal("webBackgroundImg");
if (isWeb) {
return (
+ alignItems: "center",
+ justifyContent: "center",
+ minHeight: "100svh",
+ position: "relative",
+ }}
+ >
{/* Full-viewport background for web */}
{/* Centered content column (phone-like width) */}
+ maxWidth: isWeb ? 800 : 520,
+ height: "100svh",
+ backgroundColor: "transparent",
+ }}
+ >
{children}
@@ -59,17 +58,19 @@ export default ({ currentUID = null, children }) => {
+ flexDirection: "row-reverse",
+ }}
+ >
+ }}
+ >
{children}
diff --git a/src/layouts/Page.js b/src/layouts/Page.js
index 684a3a9..00d29e6 100644
--- a/src/layouts/Page.js
+++ b/src/layouts/Page.js
@@ -1,21 +1,19 @@
/* eslint-disable react/display-name */
-import React, { useState, useEffect } from 'reactn';
-import { setGlobal } from 'reactn';
-import { Image, View } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { Motion } from '@legendapp/motion';
-import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
+import { Image, View } from "react-native";
+import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
+import { SafeAreaView } from "react-native-safe-area-context";
+import React, { setGlobal, useEffect, useState } from "reactn";
-import { responsiveHeight } from '../actions/responsiveSizes.js';
+import { responsiveHeight } from "../actions/responsiveSizes.js";
-import { Fonts, gutters } from '../styles';
+import { gutters } from "../styles";
-import BaseHeader from '../components/BaseHeader';
-import NavigateHeader from '../components/NavigateHeader';
+import BaseHeader from "../components/BaseHeader";
+import NavigateHeader from "../components/NavigateHeader";
-import { isDesktop, isWeb } from '../hooks/useLayoutType.js';
-import { useUserData } from '../providers/UserDataProvider.js';
-import { background } from '../assets/index.js';
+import { background } from "../assets/index.js";
+import { isDesktop, isWeb } from "../hooks/useLayoutType.js";
+import { useUserData } from "../providers/UserDataProvider.js";
export default ({
children,
@@ -23,11 +21,11 @@ export default ({
topStickyContent = null,
bottomStickyContent = null,
- title = '',
+ title = "",
rightComponent = null,
- containerType = 'SAFE_AREA_VIEW',
- headerType = 'BASE',
+ containerType = "SAFE_AREA_VIEW",
+ headerType = "BASE",
containerStyle = {},
headerStyle = {},
@@ -45,7 +43,7 @@ export default ({
const [scrollPosition, setScrollPosition] = useState(0);
const PageContainer =
- containerType === 'SAFE_AREA_VIEW' ? SafeAreaView : View;
+ containerType === "SAFE_AREA_VIEW" ? SafeAreaView : View;
const ContentContainer = scrollEnabled ? KeyboardAwareScrollView : View;
@@ -68,24 +66,25 @@ export default ({
{!isWeb && (
)}
- {headerType !== 'NONE' ? (
- headerType === 'BASE' ? (
+ }}
+ >
+ {headerType !== "NONE" ? (
+ headerType === "BASE" ? (
) : (
+ : {})}
+ >
{children}
diff --git a/src/screens/HitParade/HitParade.js b/src/screens/HitParade/HitParade.js
index 11a46c2..ab9bd3c 100644
--- a/src/screens/HitParade/HitParade.js
+++ b/src/screens/HitParade/HitParade.js
@@ -23,9 +23,6 @@ const HitParade = () => {
condition: true,
});
const { data: topPlaybacks } = useDataFromRef({
- // Firestore n'autorise pas 2 inégalités (>, <, >=, <=, !=) sur des champs différents.
- // On ne garde qu'une inégalité côté requête (views > 0) et on filtre ensuite côté client.
- // On surdimensionne le limit pour s'assurer d'obtenir 10 playbacks après filtrage.
ref: projectsRef.where("views", ">", 0).orderBy("views", "desc").limit(50),
format: (docs) => docs.filter((d) => d?.playbackUrl != null).slice(0, 10),
simpleRef: false,
@@ -76,7 +73,7 @@ const HitParade = () => {
style={{
...Style.containerRow,
justifyContent: "space-between",
- gap: "10%",
+ // gap: "5%",
width: "auto",
}}
>
@@ -88,7 +85,7 @@ const HitParade = () => {
onPress={() => setSelected(item)}
tint={selected === item ? "light" : "dark"}
containerStyle={{
- width: "50%",
+ width: "47%",
}}
titleStyle={{
fontSize: 16,
diff --git a/src/screens/Profile/Profile.js b/src/screens/Profile/Profile.js
index 34e52c6..14c2494 100644
--- a/src/screens/Profile/Profile.js
+++ b/src/screens/Profile/Profile.js
@@ -1,37 +1,37 @@
-import { useRoute } from '@react-navigation/native';
-import { BlurView } from 'expo-blur';
-import { Image as ExpoImage } from 'expo-image';
-import React, { useEffect, useMemo, useState } from 'react';
+import { useRoute } from "@react-navigation/native";
+import { BlurView } from "expo-blur";
+import { Image as ExpoImage } from "expo-image";
+import React, { useEffect, useMemo, useState } from "react";
import {
FlatList,
Image,
- Platform,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
-} from 'react-native';
-import { SheetManager } from 'react-native-actions-sheet';
-import { responsiveHeight } from 'react-native-responsive-dimensions';
-import { useGlobal } from 'reactn';
-import { background, icons, img } from '../../assets';
-import BorderGradient from '../../components/BorderGradient/BorderGradient';
-import MoreMenu from '../../components/MoreMenu';
-import { projectsRef, usersRef } from '../../config/firebase';
-import useDataFromRef from '../../hooks/useDataFromRef';
-import Page from '../../layouts/Page';
-import { Routes } from '../../navigation';
-import { navigate, push } from '../../navigation/NavigationService';
-import { useUser } from '../../providers/UserDataProvider';
-import { Palette } from '../../styles';
-import { FONT_FAMILY } from '../../styles/Fonts';
-import Style, { gutters, size } from '../../styles/Style';
-import MusicCard from '../Library/components/MusicCard';
-
+} from "react-native";
+import { SheetManager } from "react-native-actions-sheet";
+import { responsiveHeight } from "react-native-responsive-dimensions";
+import { useGlobal } from "reactn";
+import { background, icons, img } from "../../assets";
+import BorderGradient from "../../components/BorderGradient/BorderGradient";
+import MoreMenu from "../../components/MoreMenu";
+import { projectsRef, usersRef } from "../../config/firebase";
+import useDataFromRef from "../../hooks/useDataFromRef";
+import useLayoutType from "../../hooks/useLayoutType";
+import Page from "../../layouts/Page";
+import { Routes } from "../../navigation";
+import { navigate, push } from "../../navigation/NavigationService";
+import { useUser } from "../../providers/UserDataProvider";
+import { Palette } from "../../styles";
+import { FONT_FAMILY } from "../../styles/Fonts";
+import Style, { gutters, size } from "../../styles/Style";
+import MusicCard from "../Library/components/MusicCard";
const Profile = () => {
const { params } = useRoute();
- const [selected, setSelected] = useState('Chansons');
+ const [selected, setSelected] = useState("Chansons");
+ const { isWeb } = useLayoutType();
const {
userProjects: selfProjects,
userPlaybacks: selfPlaybacks,
@@ -41,10 +41,10 @@ const Profile = () => {
followUser,
unfollowUser,
} = useUser();
- const [currentUID] = useGlobal('currentUID');
+ const [currentUID] = useGlobal("currentUID");
const targetUserId = params?.userId || currentUID || null;
const isSelf = !!currentUID && targetUserId === currentUID;
- const [, setTooltip] = useGlobal('_tooltip');
+ const [, setTooltip] = useGlobal("_tooltip");
const [userData, setUserData] = useState(null);
const [isFollowing, setIsFollowing] = useState(false);
const [followers, setFollowers] = useState(0);
@@ -82,7 +82,7 @@ const Profile = () => {
const followingQueryRef = useMemo(() => {
try {
return targetUserId
- ? usersRef.where('followedBy', 'array-contains', targetUserId)
+ ? usersRef.where("followedBy", "array-contains", targetUserId)
: null;
} catch (e) {
return null;
@@ -124,10 +124,10 @@ const Profile = () => {
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
{
isSelf
? [
{
- label: 'Supprimer',
+ label: "Supprimer",
onPress: () =>
- SheetManager.show('Delete', {
+ SheetManager.show("Delete", {
payload: {
- title: 'Supprimer le projet',
+ title: "Supprimer le projet",
message:
- 'Cette action supprimera définitivement ce projet.',
+ "Cette action supprimera définitivement ce projet.",
onConfirm: async () => {
try {
if (!selectedProjectId) return;
await projectsRef.doc(selectedProjectId).delete();
setTooltip({
- type: 'success',
- text: 'Projet supprimé',
+ type: "success",
+ text: "Projet supprimé",
});
} catch (e) {
setTooltip({
- type: 'error',
- text: e?.message || 'Suppression impossible',
+ type: "error",
+ text: e?.message || "Suppression impossible",
});
}
},
@@ -196,7 +196,8 @@ const Profile = () => {
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
opacity: 0.8,
- }}>
+ }}
+ >
{text}
@@ -207,8 +208,8 @@ const Profile = () => {
try {
if (!targetUserId || isSelf) return null;
return projectsRef
- .where('userId', '==', targetUserId)
- .orderBy('updatedAt', 'desc');
+ .where("userId", "==", targetUserId)
+ .orderBy("updatedAt", "desc");
} catch (e) {
return null;
}
@@ -228,23 +229,24 @@ const Profile = () => {
return (
isSelf ? (
- SheetManager.show('ProfileSettings')}>
+ SheetManager.show("ProfileSettings")}>
) : null
- }>
+ }
+ >
-
+
{
// Platform.OS !== "ios" ? "dimezisBlurView" : "none"
// }
>
-
+
{
}
: img.profile
}
- cachePolicy='memory-disk'
- priority='high'
- contentFit='cover'
+ cachePolicy="memory-disk"
+ priority="high"
+ contentFit="cover"
transition={100}
style={{
...size({ size: 108 }),
@@ -285,13 +287,14 @@ const Profile = () => {
fontSize: 22,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
- }}>
+ }}
+ >
{(isSelf ? currentUserData?.userName : userData?.userName) ||
- 'Profil'}
+ "Profil"}
-
+
{Array.isArray(displayedProjects)
? displayedProjects.length
@@ -300,13 +303,14 @@ const Profile = () => {
projets
push(Routes.Follows, {
- selected: 'Abonnés',
+ selected: "Abonnés",
...(isSelf ? {} : { userId: targetUserId }),
})
- }>
+ }
+ >
{isSelf
? currentUserData?.followedBy?.length || 0
@@ -315,13 +319,14 @@ const Profile = () => {
abonnés
push(Routes.Follows, {
- selected: 'Abonnements',
+ selected: "Abonnements",
...(isSelf ? {} : { userId: targetUserId }),
})
- }>
+ }
+ >
{isSelf ? followingCount : following}
@@ -334,21 +339,23 @@ const Profile = () => {
style={{
height: 36,
borderRadius: 100,
- overflow: 'hidden',
- backgroundColor: '#FFFFFF22',
- alignItems: 'center',
- justifyContent: 'center',
- width: '80%',
- alignSelf: 'center',
+ overflow: "hidden",
+ backgroundColor: "#FFFFFF22",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "80%",
+ alignSelf: "center",
marginTop: 18,
- }}>
+ }}
+ >
- {isFollowing ? 'Ne plus suivre' : 'Suivre'}
+ }}
+ >
+ {isFollowing ? "Ne plus suivre" : "Suivre"}
@@ -359,18 +366,20 @@ const Profile = () => {
style={{
...Style.containerRow,
gap: 6,
- }}>
+ }}
+ >
{/*{["Chansons", "Playbacks", "Clips"].map((item, index) => (*/}
- {['Chansons', 'Playbacks'].map((item, index) => (
+ {["Chansons", "Playbacks"].map((item, index) => (
onPressMenu(item)}
- style={{ flex: 1 }}>
+ style={{ flex: 1 }}
+ >
{
))}
- {selected === 'Playbacks' && (
+ {selected === "Playbacks" && (
)}
- {selected === 'Chansons' && (
+ {selected === "Chansons" && (
)}
- {selected === 'Clips' && (
+ {selected === "Clips" && (
-
+
)}
@@ -437,20 +446,20 @@ const styles = StyleSheet.create({
borderWidth: 1,
borderRadius: 10,
height: 33,
- position: 'absolute',
+ position: "absolute",
zIndex: 1,
- width: '100%',
+ width: "100%",
},
blurContainer: {
height: 33,
zIndex: -1,
borderRadius: 10,
- overflow: 'hidden',
+ overflow: "hidden",
backgroundColor: Palette.glass,
},
blurView: {
- width: '100%',
- height: '100%',
+ width: "100%",
+ height: "100%",
paddingHorizontal: 10,
...Style.containerCenter,
},