feat: fixes and formatter
This commit is contained in:
@@ -1,26 +1,22 @@
|
||||
import { useRoute } from "@react-navigation/native";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { ActivityIndicator, Text, View } from "react-native";
|
||||
import { background } from "../../assets";
|
||||
import GradientButton from "../../components/GradientButton";
|
||||
import MoreMenu from "../../components/MoreMenu";
|
||||
import useNavigateToMusicDetails from "../../hooks/useNavigateToMusicDetails";
|
||||
import Page from "../../layouts/Page";
|
||||
import { Routes } from "../../navigation";
|
||||
import { navigate } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { Palette, Style, gutters } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../utils/likes";
|
||||
import MusicCard from "./components/MusicCard";
|
||||
import { useRoute } from '@react-navigation/native'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { ActivityIndicator, Text, View } from 'react-native'
|
||||
import { background } from '../../assets'
|
||||
import GradientButton from '../../components/GradientButton'
|
||||
import MoreMenu from '../../components/MoreMenu'
|
||||
import useNavigateToMusicDetails from '../../hooks/useNavigateToMusicDetails'
|
||||
import Page from '../../layouts/Page'
|
||||
import { Routes } from '../../navigation'
|
||||
import { navigate } from '../../navigation/NavigationService'
|
||||
import { useUser } from '../../providers/UserDataProvider'
|
||||
import { Palette, Style, gutters } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import { getProjectLikes, LIKE_TARGET } from '../../utils/likes'
|
||||
import MusicCard from './components/MusicCard'
|
||||
|
||||
export default function AllMyList() {
|
||||
const route = useRoute();
|
||||
const {
|
||||
title = "Mes éléments",
|
||||
scope = "music",
|
||||
liked = false,
|
||||
} = route?.params || {};
|
||||
const route = useRoute()
|
||||
const { title = 'Mes éléments', scope = 'music', liked = false } = route?.params || {}
|
||||
|
||||
const {
|
||||
userProjects,
|
||||
@@ -30,102 +26,85 @@ export default function AllMyList() {
|
||||
userPlaybacks,
|
||||
userLikedPlaybacks,
|
||||
userLikedPlaybacksLoading,
|
||||
} = useUser();
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails();
|
||||
} = useUser()
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails()
|
||||
|
||||
const items = useMemo(() => {
|
||||
if (scope === "playback") {
|
||||
if (scope === 'playback') {
|
||||
return Array.isArray(liked ? userLikedPlaybacks : userPlaybacks)
|
||||
? liked
|
||||
? userLikedPlaybacks
|
||||
: userPlaybacks
|
||||
: [];
|
||||
: []
|
||||
}
|
||||
// music (projects)
|
||||
return Array.isArray(liked ? userLikedProjects : userProjects)
|
||||
? liked
|
||||
? userLikedProjects
|
||||
: userProjects
|
||||
: [];
|
||||
}, [
|
||||
liked,
|
||||
scope,
|
||||
userLikedPlaybacks,
|
||||
userPlaybacks,
|
||||
userLikedProjects,
|
||||
userProjects,
|
||||
]);
|
||||
: []
|
||||
}, [liked, scope, userLikedPlaybacks, userPlaybacks, userLikedProjects, userProjects])
|
||||
|
||||
const sanitizedItems = Array.isArray(items) ? items : [];
|
||||
const sanitizedItems = Array.isArray(items) ? items : []
|
||||
const itemsLoading = useMemo(() => {
|
||||
if (scope === "playback") {
|
||||
return liked ? userLikedPlaybacksLoading : userProjectsLoading;
|
||||
if (scope === 'playback') {
|
||||
return liked ? userLikedPlaybacksLoading : userProjectsLoading
|
||||
}
|
||||
return liked ? userLikedProjectsLoading : userProjectsLoading;
|
||||
}, [
|
||||
liked,
|
||||
scope,
|
||||
userLikedPlaybacksLoading,
|
||||
userLikedProjectsLoading,
|
||||
userProjectsLoading,
|
||||
]);
|
||||
return liked ? userLikedProjectsLoading : userProjectsLoading
|
||||
}, [liked, scope, userLikedPlaybacksLoading, userLikedProjectsLoading, userProjectsLoading])
|
||||
|
||||
const emptyStateContent = useMemo(() => {
|
||||
const variant = liked ? "liked" : "default";
|
||||
const scopeKey = scope === "playback" ? "playback" : "music";
|
||||
const variant = liked ? 'liked' : 'default'
|
||||
const scopeKey = scope === 'playback' ? 'playback' : 'music'
|
||||
|
||||
const content = {
|
||||
music: {
|
||||
default: {
|
||||
title: "Aucune musique pour le moment",
|
||||
title: 'Aucune musique pour le moment',
|
||||
description:
|
||||
"Créez un nouveau titre ou explorez la bibliothèque pour alimenter votre collection.",
|
||||
'Créez un nouveau titre ou explorez la bibliothèque pour alimenter votre collection.',
|
||||
cta: {
|
||||
label: "Créer une musique",
|
||||
label: 'Créer une musique',
|
||||
action: () => navigate(Routes.WritingLyrics),
|
||||
},
|
||||
},
|
||||
liked: {
|
||||
title: "Aucune musique likée pour le moment",
|
||||
description:
|
||||
"Likez les morceaux qui vous inspirent pour les garder à portée de main.",
|
||||
title: 'Aucune musique likée pour le moment',
|
||||
description: 'Likez les morceaux qui vous inspirent pour les garder à portée de main.',
|
||||
cta: {
|
||||
label: "Explorer la bibliothèque",
|
||||
label: 'Explorer la bibliothèque',
|
||||
action: () => navigate(Routes.Research),
|
||||
},
|
||||
},
|
||||
},
|
||||
playback: {
|
||||
default: {
|
||||
title: "Aucun playback pour le moment",
|
||||
description:
|
||||
"Enregistrez ou importez un playback pour le retrouver facilement ici.",
|
||||
title: 'Aucun playback pour le moment',
|
||||
description: 'Enregistrez ou importez un playback pour le retrouver facilement ici.',
|
||||
cta: {
|
||||
label: "Créer un playback",
|
||||
label: 'Créer un playback',
|
||||
action: () => navigate(Routes.PlaybackOnboarding),
|
||||
},
|
||||
},
|
||||
liked: {
|
||||
title: "Aucun playback liké pour le moment",
|
||||
title: 'Aucun playback liké pour le moment',
|
||||
description:
|
||||
"Ajoutez vos playback favoris à vos likes pour les retrouver instantanément.",
|
||||
'Ajoutez vos playback favoris à vos likes pour les retrouver instantanément.',
|
||||
cta: {
|
||||
label: "Voir les playback",
|
||||
label: 'Voir les playback',
|
||||
action: () => navigate(Routes.Playbacks),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return content[scopeKey][variant];
|
||||
}, [liked, scope]);
|
||||
return content[scopeKey][variant]
|
||||
}, [liked, scope])
|
||||
|
||||
const loadingMessage = useMemo(() => {
|
||||
const target = scope === "playback" ? "playback" : "musiques";
|
||||
return liked
|
||||
? `Chargement des ${target} likés…`
|
||||
: `Chargement des ${target}…`;
|
||||
}, [liked, scope]);
|
||||
const target = scope === 'playback' ? 'playback' : 'musiques'
|
||||
return liked ? `Chargement des ${target} likés…` : `Chargement des ${target}…`
|
||||
}, [liked, scope])
|
||||
|
||||
const placeholderBaseStyle = {
|
||||
gap: 16,
|
||||
@@ -133,40 +112,40 @@ export default function AllMyList() {
|
||||
paddingHorizontal: 32,
|
||||
backgroundColor: Palette.glass,
|
||||
borderRadius: 16,
|
||||
alignSelf: "stretch",
|
||||
};
|
||||
alignSelf: 'stretch',
|
||||
}
|
||||
|
||||
const placeholderTitleStyle = {
|
||||
fontSize: 20,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
textAlign: "center",
|
||||
};
|
||||
textAlign: 'center',
|
||||
}
|
||||
|
||||
const placeholderDescriptionStyle = {
|
||||
fontSize: 14,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
opacity: 0.8,
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
maxWidth: 420,
|
||||
};
|
||||
}
|
||||
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const [menuPosition, setMenuPosition] = useState(null)
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null)
|
||||
|
||||
const onPressItem = (item) => {
|
||||
if (scope === "playback") {
|
||||
navigate(Routes.Playbacks, { projectId: item.id });
|
||||
if (scope === 'playback') {
|
||||
navigate(Routes.Playbacks, { projectId: item.id })
|
||||
} else {
|
||||
navigateToMusicDetails({
|
||||
projectId: item.id,
|
||||
songUrl: item?.songUrl,
|
||||
project: item,
|
||||
});
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Page
|
||||
@@ -184,12 +163,11 @@ export default function AllMyList() {
|
||||
</View>
|
||||
) : sanitizedItems.length > 0 ? (
|
||||
sanitizedItems.map((item) => {
|
||||
const likeTarget =
|
||||
scope === "playback" ? LIKE_TARGET.PLAYBACK : LIKE_TARGET.SONG;
|
||||
const likeTarget = scope === 'playback' ? LIKE_TARGET.PLAYBACK : LIKE_TARGET.SONG
|
||||
return (
|
||||
<MusicCard
|
||||
key={item.id}
|
||||
title={item?.title || "Sans titre"}
|
||||
title={item?.title || 'Sans titre'}
|
||||
imageUri={item?.coverUrl || null}
|
||||
subtitle={item?.userName}
|
||||
projectId={item?.id}
|
||||
@@ -197,30 +175,23 @@ export default function AllMyList() {
|
||||
likeTarget={likeTarget}
|
||||
onPress={() => onPressItem(item)}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(item.id);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null)
|
||||
);
|
||||
setSelectedProjectId(item.id)
|
||||
setMenuPosition(posTop)
|
||||
setShowMenu((prev) => !prev || posTop?.top !== (menuPosition?.top ?? null))
|
||||
}}
|
||||
/>
|
||||
);
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<View style={[Style.containerCenter, placeholderBaseStyle]}>
|
||||
<Text style={placeholderTitleStyle}>
|
||||
{emptyStateContent.title}
|
||||
</Text>
|
||||
<Text style={placeholderDescriptionStyle}>
|
||||
{emptyStateContent.description}
|
||||
</Text>
|
||||
<Text style={placeholderTitleStyle}>{emptyStateContent.title}</Text>
|
||||
<Text style={placeholderDescriptionStyle}>{emptyStateContent.description}</Text>
|
||||
{emptyStateContent?.cta ? (
|
||||
<GradientButton
|
||||
title={emptyStateContent.cta.label}
|
||||
onPress={emptyStateContent.cta.action}
|
||||
containerStyle={{
|
||||
alignSelf: "center",
|
||||
alignSelf: 'center',
|
||||
minWidth: 200,
|
||||
}}
|
||||
/>
|
||||
@@ -238,5 +209,5 @@ export default function AllMyList() {
|
||||
</View>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React from "react";
|
||||
import { Image, Platform, Pressable, Text, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { background, icons } from "../../assets";
|
||||
import Page from "../../layouts/Page";
|
||||
import { Routes } from "../../navigation";
|
||||
import { navigate } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { gutters, Palette, Style } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { size } from "../../styles/Style";
|
||||
import { BlurView } from 'expo-blur'
|
||||
import React from 'react'
|
||||
import { Image, Platform, Pressable, Text, View } from 'react-native'
|
||||
import { SheetManager } from 'react-native-actions-sheet'
|
||||
import { background, icons } from '../../assets'
|
||||
import Page from '../../layouts/Page'
|
||||
import { Routes } from '../../navigation'
|
||||
import { navigate } from '../../navigation/NavigationService'
|
||||
import { useUser } from '../../providers/UserDataProvider'
|
||||
import { gutters, Palette, Style } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import { size } from '../../styles/Style'
|
||||
const AllMyPlaylist = () => {
|
||||
const { userPlaylists = [] } = useUser();
|
||||
const { userPlaylists = [] } = useUser()
|
||||
return (
|
||||
<Page
|
||||
headerType="NAVIGATION"
|
||||
@@ -19,15 +19,9 @@ const AllMyPlaylist = () => {
|
||||
title="Mes Playlists"
|
||||
rightComponent={() => (
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
SheetManager.show("Playlist", { payload: { startAtCreate: true } })
|
||||
}
|
||||
onPress={() => SheetManager.show('Playlist', { payload: { startAtCreate: true } })}
|
||||
>
|
||||
<Image
|
||||
source={icons.add}
|
||||
style={size({ size: 20 })}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Image source={icons.add} style={size({ size: 20 })} resizeMode="contain" />
|
||||
</Pressable>
|
||||
)}
|
||||
contentContainerStyle={{
|
||||
@@ -39,13 +33,11 @@ const AllMyPlaylist = () => {
|
||||
{(Array.isArray(userPlaylists) ? userPlaylists : []).map((item) => (
|
||||
<Pressable
|
||||
key={item?.id}
|
||||
onPress={() =>
|
||||
navigate(Routes.PlaylistDetails, { playlistId: item?.id })
|
||||
}
|
||||
onPress={() => navigate(Routes.PlaylistDetails, { playlistId: item?.id })}
|
||||
>
|
||||
<View style={{ borderRadius: 12, overflow: "hidden" }}>
|
||||
<View style={{ borderRadius: 12, overflow: 'hidden' }}>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 10 : 20}
|
||||
intensity={Platform.OS !== 'ios' ? 10 : 20}
|
||||
style={{
|
||||
...Style.containerSpaceBetween,
|
||||
minHeight: 59,
|
||||
@@ -66,14 +58,14 @@ const AllMyPlaylist = () => {
|
||||
flexShrink: 1,
|
||||
}}
|
||||
>
|
||||
{item?.name || "Sans nom"}
|
||||
{item?.name || 'Sans nom'}
|
||||
</Text>
|
||||
<Pressable>
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
style={{
|
||||
...size({ size: 15 }),
|
||||
transform: [{ rotate: "-90deg" }],
|
||||
transform: [{ rotate: '-90deg' }],
|
||||
}}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
@@ -85,7 +77,7 @@ const AllMyPlaylist = () => {
|
||||
</View>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default AllMyPlaylist;
|
||||
export default AllMyPlaylist
|
||||
|
||||
@@ -1,37 +1,35 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import { Image, Pressable, Text, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { useGlobal } from "reactn";
|
||||
import { background, icons } from "../../assets";
|
||||
import MoreMenu from "../../components/MoreMenu";
|
||||
import { playlistsRef, projectsRef } from "../../config/firebase";
|
||||
import useDataFromArrayDocId from "../../hooks/useDataFromArrayId";
|
||||
import useDataFromRef from "../../hooks/useDataFromRef";
|
||||
import useNavigateToMusicDetails from "../../hooks/useNavigateToMusicDetails";
|
||||
import usePlayer from "../../hooks/usePlayer";
|
||||
import Page from "../../layouts/Page";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { gutters, Palette, Style } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { size } from "../../styles/Style";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../utils/likes";
|
||||
import MusicCard from "./components/MusicCard";
|
||||
import { BlurView } from 'expo-blur'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Image, Pressable, Text, View } from 'react-native'
|
||||
import { SheetManager } from 'react-native-actions-sheet'
|
||||
import { useGlobal } from 'reactn'
|
||||
import { background, icons } from '../../assets'
|
||||
import MoreMenu from '../../components/MoreMenu'
|
||||
import { playlistsRef, projectsRef } from '../../config/firebase'
|
||||
import useDataFromArrayDocId from '../../hooks/useDataFromArrayId'
|
||||
import useDataFromRef from '../../hooks/useDataFromRef'
|
||||
import useNavigateToMusicDetails from '../../hooks/useNavigateToMusicDetails'
|
||||
import usePlayer from '../../hooks/usePlayer'
|
||||
import Page from '../../layouts/Page'
|
||||
import { useUser } from '../../providers/UserDataProvider'
|
||||
import { gutters, Palette, Style } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import { size } from '../../styles/Style'
|
||||
import { getProjectLikes, LIKE_TARGET } from '../../utils/likes'
|
||||
import MusicCard from './components/MusicCard'
|
||||
|
||||
const AllMyPlaylist = ({ route }) => {
|
||||
const { playListId } = route?.params || {};
|
||||
const [, setTooltip] = useGlobal("_tooltip");
|
||||
const { userPlaylists = [] } = useUser();
|
||||
const [selectedPlaylistId, setSelectedPlaylistId] = useState(
|
||||
playListId || null
|
||||
);
|
||||
const { playListId } = route?.params || {}
|
||||
const [, setTooltip] = useGlobal('_tooltip')
|
||||
const { userPlaylists = [] } = useUser()
|
||||
const [selectedPlaylistId, setSelectedPlaylistId] = useState(playListId || null)
|
||||
const { data: playlist } = useDataFromRef({
|
||||
ref: selectedPlaylistId ? playlistsRef.doc(selectedPlaylistId) : null,
|
||||
simpleRef: true,
|
||||
listener: true,
|
||||
condition: !!selectedPlaylistId,
|
||||
refreshArray: [selectedPlaylistId],
|
||||
});
|
||||
})
|
||||
|
||||
// Fetch projects by ids from playlist.musics
|
||||
const { data: musics } = useDataFromArrayDocId({
|
||||
@@ -39,31 +37,31 @@ const AllMyPlaylist = ({ route }) => {
|
||||
arrayId: Array.isArray(playlist?.musics) ? playlist.musics : [],
|
||||
condition: Array.isArray(playlist?.musics) && playlist.musics.length > 0,
|
||||
refreshArray: [selectedPlaylistId, playlist?.musics?.length || 0],
|
||||
});
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails();
|
||||
const { setQueue } = usePlayer() || {};
|
||||
})
|
||||
const [menuPosition, setMenuPosition] = useState(null)
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null)
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails()
|
||||
const { setQueue } = usePlayer() || {}
|
||||
|
||||
const playlistQueueItems = useMemo(() => {
|
||||
if (!Array.isArray(musics)) return [];
|
||||
if (!Array.isArray(musics)) return []
|
||||
return musics
|
||||
.map((project) => {
|
||||
const projectId =
|
||||
typeof project?.id === "string" ? project.id : project?.projectId ?? null;
|
||||
typeof project?.id === 'string' ? project.id : (project?.projectId ?? null)
|
||||
const songUrl =
|
||||
typeof project?.songUrl === "string" && project.songUrl.length > 0
|
||||
typeof project?.songUrl === 'string' && project.songUrl.length > 0
|
||||
? project.songUrl
|
||||
: null;
|
||||
if (!songUrl) return null;
|
||||
const descriptorId = projectId ? `project-${projectId}` : songUrl;
|
||||
: null
|
||||
if (!songUrl) return null
|
||||
const descriptorId = projectId ? `project-${projectId}` : songUrl
|
||||
return {
|
||||
id: descriptorId,
|
||||
uri: songUrl,
|
||||
songUrl,
|
||||
title: project?.title || "Sans titre",
|
||||
artist: project?.userName || "",
|
||||
title: project?.title || 'Sans titre',
|
||||
artist: project?.userName || '',
|
||||
artwork: project?.coverUrl ?? null,
|
||||
coverUrl: project?.coverUrl ?? null,
|
||||
metadata: {
|
||||
@@ -76,73 +74,67 @@ const AllMyPlaylist = ({ route }) => {
|
||||
playlistId: selectedPlaylistId ?? null,
|
||||
playlistName: playlist?.name ?? null,
|
||||
},
|
||||
};
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
}, [musics, playlist?.name, selectedPlaylistId]);
|
||||
.filter(Boolean)
|
||||
}, [musics, playlist?.name, selectedPlaylistId])
|
||||
|
||||
const handlePlayFromPlaylist = useCallback(
|
||||
(project) => {
|
||||
if (!project?.id) return;
|
||||
if (!project?.id) return
|
||||
if (Array.isArray(playlistQueueItems) && playlistQueueItems.length > 0) {
|
||||
const queueIndex = playlistQueueItems.findIndex(
|
||||
(item) => item?.metadata?.projectId === project.id
|
||||
);
|
||||
if (queueIndex >= 0 && typeof setQueue === "function") {
|
||||
)
|
||||
if (queueIndex >= 0 && typeof setQueue === 'function') {
|
||||
setQueue({
|
||||
items: playlistQueueItems,
|
||||
id: selectedPlaylistId,
|
||||
type: "playlist",
|
||||
type: 'playlist',
|
||||
name: playlist?.name ?? null,
|
||||
index: queueIndex,
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
navigateToMusicDetails({
|
||||
projectId: project.id,
|
||||
songUrl: project?.songUrl,
|
||||
project,
|
||||
});
|
||||
})
|
||||
},
|
||||
[
|
||||
navigateToMusicDetails,
|
||||
playlist?.name,
|
||||
playlistQueueItems,
|
||||
selectedPlaylistId,
|
||||
setQueue,
|
||||
]
|
||||
);
|
||||
[navigateToMusicDetails, playlist?.name, playlistQueueItems, selectedPlaylistId, setQueue]
|
||||
)
|
||||
|
||||
// delete playlist
|
||||
const confirmDelete = () => {
|
||||
SheetManager.show("Delete", {
|
||||
SheetManager.show('Delete', {
|
||||
payload: {
|
||||
title: "Supprimer la playlist",
|
||||
message: "Es-tu sûr de vouloir supprimer cette playlist ?",
|
||||
title: 'Supprimer la playlist',
|
||||
message: 'Es-tu sûr de vouloir supprimer cette playlist ?',
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
if (selectedPlaylistId) {
|
||||
await playlistsRef.doc(selectedPlaylistId).delete();
|
||||
setTooltip({ type: "success", text: "Playlist supprimée" });
|
||||
await playlistsRef.doc(selectedPlaylistId).delete()
|
||||
setTooltip({ type: 'success', text: 'Playlist supprimée' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Delete playlist error", e?.message);
|
||||
console.log('Delete playlist error', e?.message)
|
||||
setTooltip({
|
||||
type: "error",
|
||||
text: e?.message || "Suppression impossible",
|
||||
});
|
||||
type: 'error',
|
||||
text: e?.message || 'Suppression impossible',
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerType="NAVIGATION"
|
||||
backgroundImg={background.libraryBG}
|
||||
title="Mes Playlists"
|
||||
width={"80%"}
|
||||
width={'80%'}
|
||||
contentContainerStyle={{
|
||||
paddingBottom: gutters * 2,
|
||||
}}
|
||||
@@ -156,7 +148,7 @@ const AllMyPlaylist = ({ route }) => {
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<View style={{ flexDirection: "row", gap: 20 }}>
|
||||
<View style={{ flexDirection: 'row', gap: 20 }}>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
@@ -168,67 +160,62 @@ const AllMyPlaylist = ({ route }) => {
|
||||
>
|
||||
<View style={{ flex: 1, gap: 12 }}>
|
||||
<View style={{ gap: 8 }}>
|
||||
{(Array.isArray(userPlaylists) ? userPlaylists : []).map(
|
||||
(item) => {
|
||||
const isSelected = selectedPlaylistId === item?.id;
|
||||
{(Array.isArray(userPlaylists) ? userPlaylists : []).map((item) => {
|
||||
const isSelected = selectedPlaylistId === item?.id
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
key={item?.id}
|
||||
onPress={() => setSelectedPlaylistId(item?.id)}
|
||||
return (
|
||||
<Pressable key={item?.id} onPress={() => setSelectedPlaylistId(item?.id)}>
|
||||
<View
|
||||
style={{
|
||||
borderRadius: 14,
|
||||
overflow: 'hidden',
|
||||
borderWidth: 1,
|
||||
borderColor: Palette.transparentWhite,
|
||||
transform: [{ scaleX: isSelected ? 1.04 : 1 }],
|
||||
}}
|
||||
>
|
||||
<View
|
||||
<BlurView
|
||||
intensity={30}
|
||||
style={{
|
||||
borderRadius: 14,
|
||||
overflow: "hidden",
|
||||
borderWidth: 1,
|
||||
borderColor: Palette.transparentWhite,
|
||||
transform: [{ scaleX: isSelected ? 1.04 : 1 }],
|
||||
...Style.containerSpaceBetween,
|
||||
minHeight: 59,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
}}
|
||||
>
|
||||
<BlurView
|
||||
intensity={30}
|
||||
<Text
|
||||
style={{
|
||||
...Style.containerSpaceBetween,
|
||||
minHeight: 59,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
flex: 1,
|
||||
fontSize: isSelected ? 18 : 16,
|
||||
color: Palette.white,
|
||||
fontFamily: isSelected
|
||||
? FONT_FAMILY.InterSemiBold
|
||||
: FONT_FAMILY.InterRegular,
|
||||
marginRight: 12,
|
||||
flexShrink: 1,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
{item?.name || 'Sans nom'}
|
||||
</Text>
|
||||
<Pressable>
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
style={{
|
||||
flex: 1,
|
||||
fontSize: isSelected ? 18 : 16,
|
||||
color: Palette.white,
|
||||
fontFamily: isSelected
|
||||
? FONT_FAMILY.InterSemiBold
|
||||
: FONT_FAMILY.InterRegular,
|
||||
marginRight: 12,
|
||||
flexShrink: 1,
|
||||
...size({ size: 15 }),
|
||||
transform: [{ rotate: '-90deg' }],
|
||||
}}
|
||||
>
|
||||
{item?.name || "Sans nom"}
|
||||
</Text>
|
||||
<Pressable>
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
style={{
|
||||
...size({ size: 15 }),
|
||||
transform: [{ rotate: "-90deg" }],
|
||||
}}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
</BlurView>
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
)}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
</BlurView>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
SheetManager.show("Playlist", {
|
||||
SheetManager.show('Playlist', {
|
||||
payload: { startAtCreate: true },
|
||||
})
|
||||
}
|
||||
@@ -236,7 +223,7 @@ const AllMyPlaylist = ({ route }) => {
|
||||
<View
|
||||
style={{
|
||||
borderRadius: 12,
|
||||
overflow: "hidden",
|
||||
overflow: 'hidden',
|
||||
borderWidth: 1,
|
||||
borderColor: Palette.transparentWhite,
|
||||
}}
|
||||
@@ -259,11 +246,7 @@ const AllMyPlaylist = ({ route }) => {
|
||||
>
|
||||
Ajouter une playlist
|
||||
</Text>
|
||||
<Image
|
||||
source={icons.add}
|
||||
style={size({ size: 20 })}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Image source={icons.add} style={size({ size: 20 })} resizeMode="contain" />
|
||||
</BlurView>
|
||||
</View>
|
||||
</Pressable>
|
||||
@@ -282,12 +265,9 @@ const AllMyPlaylist = ({ route }) => {
|
||||
likeTarget={LIKE_TARGET.SONG}
|
||||
onPress={() => handlePlayFromPlaylist(p)}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null)
|
||||
);
|
||||
setSelectedProjectId(p.id)
|
||||
setMenuPosition(posTop)
|
||||
setShowMenu((prev) => !prev || posTop?.top !== (menuPosition?.top ?? null))
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -304,7 +284,7 @@ const AllMyPlaylist = ({ route }) => {
|
||||
</View>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default AllMyPlaylist;
|
||||
export default AllMyPlaylist
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React from "react";
|
||||
import {
|
||||
Image,
|
||||
Platform,
|
||||
Pressable,
|
||||
ScrollView,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||
import { background, icons } from "../../assets";
|
||||
import SearchBar from "../../components/SearchBar";
|
||||
import MobileCoinBadge from "../../components/MobileCoinBadge";
|
||||
import ShareBtn from "../../components/ShareBtn/ShareBtn";
|
||||
import Page from "../../layouts/Page";
|
||||
import { Routes } from "../../navigation";
|
||||
import { navigate } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import BackTracks from "./components/BackTracks";
|
||||
import LikedClips from "./components/LikedClips";
|
||||
import LikedMusic from "./components/LikedMusic";
|
||||
import LikedPlayback from "./components/LikedPlayback";
|
||||
import MyClips from "./components/MyClips";
|
||||
import MyMusic from "./components/MyMusic";
|
||||
import MyPlaylist from "./components/MyPlaylist";
|
||||
import { BlurView } from 'expo-blur'
|
||||
import React from 'react'
|
||||
import { Image, Platform, Pressable, ScrollView, Text, View } from 'react-native'
|
||||
import { responsiveHeight } from 'react-native-responsive-dimensions'
|
||||
import { background, icons } from '../../assets'
|
||||
import SearchBar from '../../components/SearchBar'
|
||||
import MobileCoinBadge from '../../components/MobileCoinBadge'
|
||||
import ShareBtn from '../../components/ShareBtn/ShareBtn'
|
||||
import Page from '../../layouts/Page'
|
||||
import { Routes } from '../../navigation'
|
||||
import { navigate } from '../../navigation/NavigationService'
|
||||
import { useUser } from '../../providers/UserDataProvider'
|
||||
import { Palette } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import BackTracks from './components/BackTracks'
|
||||
import LikedClips from './components/LikedClips'
|
||||
import LikedMusic from './components/LikedMusic'
|
||||
import LikedPlayback from './components/LikedPlayback'
|
||||
import MyClips from './components/MyClips'
|
||||
import MyMusic from './components/MyMusic'
|
||||
import MyPlaylist from './components/MyPlaylist'
|
||||
|
||||
const Library = () => {
|
||||
const {
|
||||
@@ -34,19 +27,16 @@ const Library = () => {
|
||||
userLikedProjects = [],
|
||||
userLikedPlaybacks = [],
|
||||
userPlaylists = [],
|
||||
} = useUser() || {};
|
||||
} = useUser() || {}
|
||||
|
||||
const hasMyMusic = Array.isArray(userProjects) && userProjects.length > 0;
|
||||
const hasBackTracks =
|
||||
Array.isArray(userPlaybacks) && userPlaybacks.length > 0;
|
||||
const hasLikedMusic =
|
||||
Array.isArray(userLikedProjects) && userLikedProjects.length > 0;
|
||||
const hasLikedPlayback =
|
||||
Array.isArray(userLikedPlaybacks) && userLikedPlaybacks.length > 0;
|
||||
const hasPlaylists = Array.isArray(userPlaylists) && userPlaylists.length > 0;
|
||||
const hasMyMusic = Array.isArray(userProjects) && userProjects.length > 0
|
||||
const hasBackTracks = Array.isArray(userPlaybacks) && userPlaybacks.length > 0
|
||||
const hasLikedMusic = Array.isArray(userLikedProjects) && userLikedProjects.length > 0
|
||||
const hasLikedPlayback = Array.isArray(userLikedPlaybacks) && userLikedPlaybacks.length > 0
|
||||
const hasPlaylists = Array.isArray(userPlaylists) && userPlaylists.length > 0
|
||||
|
||||
const hasMyClips = false; // À modifier quand les vraies données seront disponibles
|
||||
const hasLikedClips = false; // À modifier quand les vraies données seront disponibles
|
||||
const hasMyClips = false // À modifier quand les vraies données seront disponibles
|
||||
const hasLikedClips = false // À modifier quand les vraies données seront disponibles
|
||||
|
||||
const hasAnySection =
|
||||
hasMyMusic ||
|
||||
@@ -55,17 +45,17 @@ const Library = () => {
|
||||
hasLikedPlayback ||
|
||||
hasPlaylists ||
|
||||
hasMyClips ||
|
||||
hasLikedClips;
|
||||
hasLikedClips
|
||||
|
||||
return (
|
||||
<Page backgroundImg={background.libraryBG} headerType="NONE">
|
||||
{Platform.OS !== "web" ? (
|
||||
{Platform.OS !== 'web' ? (
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: 12,
|
||||
marginBottom: 6,
|
||||
}}
|
||||
@@ -77,7 +67,7 @@ const Library = () => {
|
||||
<View style={{ gap: 17, paddingBottom: 20 }}>
|
||||
<Image
|
||||
source={icons.musicLandLogo}
|
||||
style={{ alignSelf: "center", height: 150, resizeMode: "contain" }}
|
||||
style={{ alignSelf: 'center', height: 150, resizeMode: 'contain' }}
|
||||
/>
|
||||
<Pressable onPress={() => navigate(Routes.Research)}>
|
||||
<SearchBar
|
||||
@@ -94,14 +84,14 @@ const Library = () => {
|
||||
flexGrow: 1,
|
||||
gap: 20,
|
||||
paddingBottom: responsiveHeight(20),
|
||||
paddingTop: Platform.OS !== "android" ? 20 : 0,
|
||||
paddingTop: Platform.OS !== 'android' ? 20 : 0,
|
||||
}}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<BlurView
|
||||
intensity={20}
|
||||
experimentalBlurMethod="dimezisBlurView"
|
||||
style={{ borderRadius: 12, padding: 12, overflow: "hidden" }}
|
||||
style={{ borderRadius: 12, padding: 12, overflow: 'hidden' }}
|
||||
>
|
||||
<MyMusic />
|
||||
</BlurView>
|
||||
@@ -116,8 +106,8 @@ const Library = () => {
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingTop: 40,
|
||||
}}
|
||||
>
|
||||
@@ -127,7 +117,7 @@ const Library = () => {
|
||||
color: Palette.white,
|
||||
opacity: 0.8,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Rien n'est disponible encore ici
|
||||
@@ -137,7 +127,7 @@ const Library = () => {
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Library;
|
||||
export default Library
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Image, Platform, ScrollView, StyleSheet, Text, View } from "react-native";
|
||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||
import { background, icons } from "../../assets";
|
||||
import SearchBar from "../../components/SearchBar";
|
||||
import useSearch from "../../hooks/useSearch";
|
||||
import Page from "../../layouts/Page";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { Palette, Style } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import BackTracks from "./components/BackTracks";
|
||||
import LikedMusic from "./components/LikedMusic";
|
||||
import LikedPlayback from "./components/LikedPlayback";
|
||||
import MyMusic from "./components/MyMusic";
|
||||
import MyPlaylist from "./components/MyPlaylist";
|
||||
import ResearchHeader from "./components/ResearchHeader";
|
||||
import SearchResultsList from "./components/SearchResultsList";
|
||||
import { BlurView } from 'expo-blur'
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { Image, Platform, ScrollView, StyleSheet, Text, View } from 'react-native'
|
||||
import { responsiveHeight } from 'react-native-responsive-dimensions'
|
||||
import { background, icons } from '../../assets'
|
||||
import SearchBar from '../../components/SearchBar'
|
||||
import useSearch from '../../hooks/useSearch'
|
||||
import Page from '../../layouts/Page'
|
||||
import { useUser } from '../../providers/UserDataProvider'
|
||||
import { Palette, Style } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import BackTracks from './components/BackTracks'
|
||||
import LikedMusic from './components/LikedMusic'
|
||||
import LikedPlayback from './components/LikedPlayback'
|
||||
import MyMusic from './components/MyMusic'
|
||||
import MyPlaylist from './components/MyPlaylist'
|
||||
import ResearchHeader from './components/ResearchHeader'
|
||||
import SearchResultsList from './components/SearchResultsList'
|
||||
const Library = () => {
|
||||
const {
|
||||
userProjects = [],
|
||||
@@ -29,19 +23,16 @@ const Library = () => {
|
||||
userLikedProjects = [],
|
||||
userLikedPlaybacks = [],
|
||||
userPlaylists = [],
|
||||
} = useUser() || {};
|
||||
} = useUser() || {}
|
||||
|
||||
const hasMyMusic = Array.isArray(userProjects) && userProjects.length > 0;
|
||||
const hasBackTracks =
|
||||
Array.isArray(userPlaybacks) && userPlaybacks.length > 0;
|
||||
const hasLikedMusic =
|
||||
Array.isArray(userLikedProjects) && userLikedProjects.length > 0;
|
||||
const hasLikedPlayback =
|
||||
Array.isArray(userLikedPlaybacks) && userLikedPlaybacks.length > 0;
|
||||
const hasPlaylists = Array.isArray(userPlaylists) && userPlaylists.length > 0;
|
||||
const hasMyMusic = Array.isArray(userProjects) && userProjects.length > 0
|
||||
const hasBackTracks = Array.isArray(userPlaybacks) && userPlaybacks.length > 0
|
||||
const hasLikedMusic = Array.isArray(userLikedProjects) && userLikedProjects.length > 0
|
||||
const hasLikedPlayback = Array.isArray(userLikedPlaybacks) && userLikedPlaybacks.length > 0
|
||||
const hasPlaylists = Array.isArray(userPlaylists) && userPlaylists.length > 0
|
||||
|
||||
const hasMyClips = false; // À modifier quand les vraies données seront disponibles
|
||||
const hasLikedClips = false; // À modifier quand les vraies données seront disponibles
|
||||
const hasMyClips = false // À modifier quand les vraies données seront disponibles
|
||||
const hasLikedClips = false // À modifier quand les vraies données seront disponibles
|
||||
|
||||
const hasAnySection =
|
||||
hasMyMusic ||
|
||||
@@ -50,7 +41,7 @@ const Library = () => {
|
||||
hasLikedPlayback ||
|
||||
hasPlaylists ||
|
||||
hasMyClips ||
|
||||
hasLikedClips;
|
||||
hasLikedClips
|
||||
|
||||
const {
|
||||
search,
|
||||
@@ -61,96 +52,81 @@ const Library = () => {
|
||||
musics = [],
|
||||
playbacks = [],
|
||||
loading,
|
||||
} = useSearch();
|
||||
} = useSearch()
|
||||
|
||||
const toggleSelected = useCallback(
|
||||
(value) => {
|
||||
setSelected((previous) => (previous === value ? null : value));
|
||||
setSelected((previous) => (previous === value ? null : value))
|
||||
},
|
||||
[setSelected]
|
||||
);
|
||||
)
|
||||
|
||||
const musicResults = useMemo(
|
||||
() => (Array.isArray(musics) ? musics : []),
|
||||
[musics]
|
||||
);
|
||||
const musicResults = useMemo(() => (Array.isArray(musics) ? musics : []), [musics])
|
||||
|
||||
const playbackResults = useMemo(
|
||||
() => (Array.isArray(playbacks) ? playbacks : []),
|
||||
[playbacks]
|
||||
);
|
||||
const playbackResults = useMemo(() => (Array.isArray(playbacks) ? playbacks : []), [playbacks])
|
||||
|
||||
const userResults = useMemo(
|
||||
() => (Array.isArray(users) ? users : []),
|
||||
[users]
|
||||
);
|
||||
const userResults = useMemo(() => (Array.isArray(users) ? users : []), [users])
|
||||
|
||||
const musicsLoading = loading;
|
||||
const playbacksLoading = loading;
|
||||
const usersLoading = loading;
|
||||
const musicsLoading = loading
|
||||
const playbacksLoading = loading
|
||||
const usersLoading = loading
|
||||
|
||||
const [dropdownVisible, setDropdownVisible] = useState(false);
|
||||
const searchWrapperRef = useRef(null);
|
||||
const hasSearchQuery = search.trim().length > 0;
|
||||
const [dropdownVisible, setDropdownVisible] = useState(false)
|
||||
const searchWrapperRef = useRef(null)
|
||||
const hasSearchQuery = search.trim().length > 0
|
||||
|
||||
const closeDropdown = useCallback(() => {
|
||||
setDropdownVisible(false);
|
||||
setSelected(null);
|
||||
setSearch("");
|
||||
}, [setSelected, setSearch]);
|
||||
setDropdownVisible(false)
|
||||
setSelected(null)
|
||||
setSearch('')
|
||||
}, [setSelected, setSearch])
|
||||
|
||||
const handleFocus = () => {
|
||||
setDropdownVisible(true);
|
||||
};
|
||||
setDropdownVisible(true)
|
||||
}
|
||||
|
||||
const shouldShowResults = dropdownVisible;
|
||||
const shouldBlurContent = dropdownVisible;
|
||||
const shouldShowResults = dropdownVisible
|
||||
const shouldBlurContent = dropdownVisible
|
||||
|
||||
const handleChangeText = (value) => {
|
||||
setSearch(value);
|
||||
setDropdownVisible(true);
|
||||
};
|
||||
setSearch(value)
|
||||
setDropdownVisible(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!dropdownVisible) return undefined;
|
||||
if (!dropdownVisible) return undefined
|
||||
|
||||
const handleClickOutside = (event) => {
|
||||
if (searchWrapperRef.current?.contains(event.target)) return;
|
||||
closeDropdown();
|
||||
};
|
||||
if (searchWrapperRef.current?.contains(event.target)) return
|
||||
closeDropdown()
|
||||
}
|
||||
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
document.addEventListener("touchstart", handleClickOutside);
|
||||
document.addEventListener('mousedown', handleClickOutside)
|
||||
document.addEventListener('touchstart', handleClickOutside)
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
document.removeEventListener("touchstart", handleClickOutside);
|
||||
};
|
||||
}, [dropdownVisible, closeDropdown]);
|
||||
document.removeEventListener('mousedown', handleClickOutside)
|
||||
document.removeEventListener('touchstart', handleClickOutside)
|
||||
}
|
||||
}, [dropdownVisible, closeDropdown])
|
||||
|
||||
return (
|
||||
<Page
|
||||
backgroundImg={background.libraryBgWeb}
|
||||
headerType="NONE"
|
||||
width={"80%"}
|
||||
>
|
||||
<View
|
||||
style={{ gap: 17, paddingBottom: 20, zIndex: dropdownVisible ? 40 : 1 }}
|
||||
>
|
||||
<Page backgroundImg={background.libraryBgWeb} headerType="NONE" width={'80%'}>
|
||||
<View style={{ gap: 17, paddingBottom: 20, zIndex: dropdownVisible ? 40 : 1 }}>
|
||||
<Image
|
||||
source={icons.musicLandLogo}
|
||||
style={{ alignSelf: "center", height: 150, resizeMode: "contain" }}
|
||||
style={{ alignSelf: 'center', height: 150, resizeMode: 'contain' }}
|
||||
/>
|
||||
<View
|
||||
ref={searchWrapperRef}
|
||||
style={{
|
||||
position: "relative",
|
||||
alignSelf: "center",
|
||||
width: "65%",
|
||||
position: 'relative',
|
||||
alignSelf: 'center',
|
||||
width: '65%',
|
||||
maxWidth: 520,
|
||||
minWidth: 360,
|
||||
zIndex: 40,
|
||||
overflow: "visible",
|
||||
overflow: 'visible',
|
||||
}}
|
||||
>
|
||||
<SearchBar
|
||||
@@ -164,12 +140,12 @@ const Library = () => {
|
||||
{shouldShowResults && (
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
top: 60,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 50,
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@@ -179,7 +155,7 @@ const Library = () => {
|
||||
padding: 16,
|
||||
backgroundColor: Palette.ultraLightWhite,
|
||||
...Style.defaultBorder,
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
zIndex: 50,
|
||||
elevation: 12,
|
||||
}}
|
||||
@@ -205,7 +181,7 @@ const Library = () => {
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ flex: 1, position: "relative" }}>
|
||||
<View style={{ flex: 1, position: 'relative' }}>
|
||||
{shouldBlurContent && (
|
||||
<BlurView
|
||||
intensity={35}
|
||||
@@ -215,8 +191,8 @@ const Library = () => {
|
||||
{
|
||||
zIndex: 10,
|
||||
borderRadius: 18,
|
||||
backgroundColor: "rgba(0, 0, 0, 0.25)",
|
||||
overflow: "hidden",
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.25)',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -226,15 +202,15 @@ const Library = () => {
|
||||
flexGrow: 1,
|
||||
gap: 20,
|
||||
paddingBottom: responsiveHeight(20),
|
||||
paddingTop: Platform.OS !== "android" ? 20 : 0,
|
||||
paddingTop: Platform.OS !== 'android' ? 20 : 0,
|
||||
}}
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={{ flex: 1, position: "relative", zIndex: 5 }}
|
||||
style={{ flex: 1, position: 'relative', zIndex: 5 }}
|
||||
>
|
||||
<BlurView
|
||||
intensity={40}
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexDirection: 'row',
|
||||
gap: 20,
|
||||
padding: 10,
|
||||
borderRadius: 12,
|
||||
@@ -252,7 +228,7 @@ const Library = () => {
|
||||
|
||||
<BlurView
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexDirection: 'row',
|
||||
gap: 20,
|
||||
padding: 10,
|
||||
borderRadius: 12,
|
||||
@@ -275,8 +251,8 @@ const Library = () => {
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingTop: 40,
|
||||
}}
|
||||
>
|
||||
@@ -286,7 +262,7 @@ const Library = () => {
|
||||
color: Palette.white,
|
||||
opacity: 0.8,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Rien n'est disponible encore ici
|
||||
@@ -296,7 +272,7 @@ const Library = () => {
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Library;
|
||||
export default Library
|
||||
|
||||
+367
-457
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,25 +1,25 @@
|
||||
import { useRoute } from "@react-navigation/native";
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import { Image, Pressable, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { useDataFromRef } from "react-native-minuit/src/hooks";
|
||||
import useDataFromArrayId from "react-native-minuit/src/hooks/useDataFromArrayId";
|
||||
import { useGlobal } from "reactn";
|
||||
import { background, icons } from "../../assets";
|
||||
import MoreMenu from "../../components/MoreMenu";
|
||||
import { playlistsRef, projectsRef } from "../../config/firebase";
|
||||
import useNavigateToMusicDetails from "../../hooks/useNavigateToMusicDetails";
|
||||
import usePlayer from "../../hooks/usePlayer";
|
||||
import Page from "../../layouts/Page";
|
||||
import { goBack } from "../../navigation/NavigationService";
|
||||
import { gutters } from "../../styles";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../utils/likes";
|
||||
import MusicCard from "./components/MusicCard";
|
||||
import { useRoute } from '@react-navigation/native'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Image, Pressable, View } from 'react-native'
|
||||
import { SheetManager } from 'react-native-actions-sheet'
|
||||
import { useDataFromRef } from 'react-native-minuit/src/hooks'
|
||||
import useDataFromArrayId from 'react-native-minuit/src/hooks/useDataFromArrayId'
|
||||
import { useGlobal } from 'reactn'
|
||||
import { background, icons } from '../../assets'
|
||||
import MoreMenu from '../../components/MoreMenu'
|
||||
import { playlistsRef, projectsRef } from '../../config/firebase'
|
||||
import useNavigateToMusicDetails from '../../hooks/useNavigateToMusicDetails'
|
||||
import usePlayer from '../../hooks/usePlayer'
|
||||
import Page from '../../layouts/Page'
|
||||
import { goBack } from '../../navigation/NavigationService'
|
||||
import { gutters } from '../../styles'
|
||||
import { getProjectLikes, LIKE_TARGET } from '../../utils/likes'
|
||||
import MusicCard from './components/MusicCard'
|
||||
|
||||
const PlaylistDetails = () => {
|
||||
const [, setTooltip] = useGlobal("_tooltip");
|
||||
const route = useRoute();
|
||||
const playlistId = route?.params?.playlistId;
|
||||
const [, setTooltip] = useGlobal('_tooltip')
|
||||
const route = useRoute()
|
||||
const playlistId = route?.params?.playlistId
|
||||
|
||||
// Fetch the playlist document
|
||||
const { data: playlist } = useDataFromRef({
|
||||
@@ -28,7 +28,7 @@ const PlaylistDetails = () => {
|
||||
listener: true,
|
||||
condition: !!playlistId,
|
||||
refreshArray: [playlistId],
|
||||
});
|
||||
})
|
||||
|
||||
// Fetch projects by ids from playlist.musics
|
||||
const { data: musics } = useDataFromArrayId({
|
||||
@@ -36,32 +36,32 @@ const PlaylistDetails = () => {
|
||||
arrayId: Array.isArray(playlist?.musics) ? playlist.musics : [],
|
||||
condition: Array.isArray(playlist?.musics) && playlist.musics.length > 0,
|
||||
refreshArray: [playlistId, playlist?.musics?.length || 0],
|
||||
});
|
||||
})
|
||||
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails();
|
||||
const { setQueue } = usePlayer() || {};
|
||||
const [menuPosition, setMenuPosition] = useState(null)
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null)
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails()
|
||||
const { setQueue } = usePlayer() || {}
|
||||
|
||||
const playlistQueueItems = useMemo(() => {
|
||||
if (!Array.isArray(musics)) return [];
|
||||
if (!Array.isArray(musics)) return []
|
||||
return musics
|
||||
.map((project) => {
|
||||
const projectId =
|
||||
typeof project?.id === "string" ? project.id : project?.projectId ?? null;
|
||||
typeof project?.id === 'string' ? project.id : (project?.projectId ?? null)
|
||||
const songUrl =
|
||||
typeof project?.songUrl === "string" && project.songUrl.length > 0
|
||||
typeof project?.songUrl === 'string' && project.songUrl.length > 0
|
||||
? project.songUrl
|
||||
: null;
|
||||
if (!songUrl) return null;
|
||||
const descriptorId = projectId ? `project-${projectId}` : songUrl;
|
||||
: null
|
||||
if (!songUrl) return null
|
||||
const descriptorId = projectId ? `project-${projectId}` : songUrl
|
||||
return {
|
||||
id: descriptorId,
|
||||
uri: songUrl,
|
||||
songUrl,
|
||||
title: project?.title || "Sans titre",
|
||||
artist: project?.userName || "",
|
||||
title: project?.title || 'Sans titre',
|
||||
artist: project?.userName || '',
|
||||
artwork: project?.coverUrl ?? null,
|
||||
coverUrl: project?.coverUrl ?? null,
|
||||
metadata: {
|
||||
@@ -74,73 +74,67 @@ const PlaylistDetails = () => {
|
||||
playlistId: playlistId ?? null,
|
||||
playlistName: playlist?.name ?? null,
|
||||
},
|
||||
};
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
}, [musics, playlist?.name, playlistId]);
|
||||
.filter(Boolean)
|
||||
}, [musics, playlist?.name, playlistId])
|
||||
|
||||
const handlePlayFromPlaylist = useCallback(
|
||||
(project) => {
|
||||
if (!project?.id) return;
|
||||
if (!project?.id) return
|
||||
if (Array.isArray(playlistQueueItems) && playlistQueueItems.length > 0) {
|
||||
const queueIndex = playlistQueueItems.findIndex(
|
||||
(item) => item?.metadata?.projectId === project.id
|
||||
);
|
||||
if (queueIndex >= 0 && typeof setQueue === "function") {
|
||||
)
|
||||
if (queueIndex >= 0 && typeof setQueue === 'function') {
|
||||
setQueue({
|
||||
items: playlistQueueItems,
|
||||
id: playlistId,
|
||||
type: "playlist",
|
||||
type: 'playlist',
|
||||
name: playlist?.name ?? null,
|
||||
index: queueIndex,
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
navigateToMusicDetails({
|
||||
projectId: project.id,
|
||||
songUrl: project?.songUrl,
|
||||
project,
|
||||
});
|
||||
})
|
||||
},
|
||||
[
|
||||
navigateToMusicDetails,
|
||||
playlist?.name,
|
||||
playlistId,
|
||||
playlistQueueItems,
|
||||
setQueue,
|
||||
]
|
||||
);
|
||||
[navigateToMusicDetails, playlist?.name, playlistId, playlistQueueItems, setQueue]
|
||||
)
|
||||
|
||||
const confirmDelete = () => {
|
||||
SheetManager.show("Delete", {
|
||||
SheetManager.show('Delete', {
|
||||
payload: {
|
||||
title: "Supprimer la playlist",
|
||||
message: "Es-tu sûr de vouloir supprimer cette playlist ?",
|
||||
title: 'Supprimer la playlist',
|
||||
message: 'Es-tu sûr de vouloir supprimer cette playlist ?',
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
if (playlistId) {
|
||||
await playlistsRef.doc(playlistId).delete();
|
||||
setTooltip({ type: "success", text: "Playlist supprimée" });
|
||||
await playlistsRef.doc(playlistId).delete()
|
||||
setTooltip({ type: 'success', text: 'Playlist supprimée' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Delete playlist error", e?.message);
|
||||
console.log('Delete playlist error', e?.message)
|
||||
setTooltip({
|
||||
type: "error",
|
||||
text: e?.message || "Suppression impossible",
|
||||
});
|
||||
type: 'error',
|
||||
text: e?.message || 'Suppression impossible',
|
||||
})
|
||||
} finally {
|
||||
goBack();
|
||||
goBack()
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerType="NAVIGATION"
|
||||
backgroundImg={background.libraryBG}
|
||||
title={playlist?.name || "Playlist"}
|
||||
title={playlist?.name || 'Playlist'}
|
||||
rightComponent={() => (
|
||||
<Pressable onPress={confirmDelete}>
|
||||
<Image source={icons.trash} style={{ width: 24, height: 24 }} />
|
||||
@@ -161,11 +155,9 @@ const PlaylistDetails = () => {
|
||||
likeTarget={LIKE_TARGET.SONG}
|
||||
onPress={() => handlePlayFromPlaylist(p)}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) => !prev || posTop?.top !== (menuPosition?.top ?? null)
|
||||
);
|
||||
setSelectedProjectId(p.id)
|
||||
setMenuPosition(posTop)
|
||||
setShowMenu((prev) => !prev || posTop?.top !== (menuPosition?.top ?? null))
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -181,7 +173,7 @@ const PlaylistDetails = () => {
|
||||
/>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default PlaylistDetails;
|
||||
export default PlaylistDetails
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { playlistsRef } from "../../../config/firebase";
|
||||
import { playlistsRef } from '../../../config/firebase'
|
||||
|
||||
export const createPlaylist = async (payload = {}) => {
|
||||
try {
|
||||
const createdBy = payload?.createdBy;
|
||||
const name = payload?.name?.trim?.();
|
||||
const musics = Array.isArray(payload?.musics) ? payload.musics : [];
|
||||
const createdBy = payload?.createdBy
|
||||
const name = payload?.name?.trim?.()
|
||||
const musics = Array.isArray(payload?.musics) ? payload.musics : []
|
||||
|
||||
const doc = {
|
||||
createdBy,
|
||||
@@ -12,12 +12,12 @@ export const createPlaylist = async (payload = {}) => {
|
||||
musics,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
}
|
||||
|
||||
const docRef = await playlistsRef.add(doc);
|
||||
return docRef.id;
|
||||
const docRef = await playlistsRef.add(doc)
|
||||
return docRef.id
|
||||
} catch (error) {
|
||||
console.error("Error creating playlist:", error);
|
||||
throw error;
|
||||
console.error('Error creating playlist:', error)
|
||||
throw error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
import { View } from "react-native";
|
||||
import { background } from "../../assets";
|
||||
import useSearch from "../../hooks/useSearch";
|
||||
import Page from "../../layouts/Page";
|
||||
import { gutters } from "../../styles";
|
||||
import ResearchHeader from "./components/ResearchHeader";
|
||||
import SearchResultsList from "./components/SearchResultsList";
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { background } from '../../assets'
|
||||
import useSearch from '../../hooks/useSearch'
|
||||
import Page from '../../layouts/Page'
|
||||
import { gutters } from '../../styles'
|
||||
import ResearchHeader from './components/ResearchHeader'
|
||||
import SearchResultsList from './components/SearchResultsList'
|
||||
|
||||
const Research = () => {
|
||||
const {
|
||||
@@ -17,33 +17,24 @@ const Research = () => {
|
||||
musics = [],
|
||||
playbacks = [],
|
||||
loading,
|
||||
} = useSearch();
|
||||
} = useSearch()
|
||||
|
||||
const toggleSelected = useCallback(
|
||||
(value) => {
|
||||
setSelected((previous) => (previous === value ? null : value));
|
||||
setSelected((previous) => (previous === value ? null : value))
|
||||
},
|
||||
[setSelected],
|
||||
);
|
||||
[setSelected]
|
||||
)
|
||||
|
||||
const musicResults = useMemo(
|
||||
() => (Array.isArray(musics) ? musics : []),
|
||||
[musics],
|
||||
);
|
||||
const musicResults = useMemo(() => (Array.isArray(musics) ? musics : []), [musics])
|
||||
|
||||
const playbackResults = useMemo(
|
||||
() => (Array.isArray(playbacks) ? playbacks : []),
|
||||
[playbacks],
|
||||
);
|
||||
const playbackResults = useMemo(() => (Array.isArray(playbacks) ? playbacks : []), [playbacks])
|
||||
|
||||
const userResults = useMemo(
|
||||
() => (Array.isArray(users) ? users : []),
|
||||
[users],
|
||||
);
|
||||
const userResults = useMemo(() => (Array.isArray(users) ? users : []), [users])
|
||||
|
||||
const musicsLoading = loading;
|
||||
const playbacksLoading = loading;
|
||||
const usersLoading = loading;
|
||||
const musicsLoading = loading
|
||||
const playbacksLoading = loading
|
||||
const usersLoading = loading
|
||||
|
||||
return (
|
||||
<Page
|
||||
@@ -72,7 +63,7 @@ const Research = () => {
|
||||
/>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Research;
|
||||
export default Research
|
||||
|
||||
@@ -1,47 +1,35 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
Pressable,
|
||||
Text,
|
||||
View,
|
||||
useWindowDimensions,
|
||||
} from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import GradientButton from "../../../components/GradientButton";
|
||||
import useLayoutType from "../../../hooks/useLayoutType";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUserData } from "../../../providers/UserDataProvider";
|
||||
import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import CardContainer from "./CardContainer";
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { FlatList, Image, Pressable, Text, View, useWindowDimensions } from 'react-native'
|
||||
import { SheetManager } from 'react-native-actions-sheet'
|
||||
import GradientButton from '../../../components/GradientButton'
|
||||
import useLayoutType from '../../../hooks/useLayoutType'
|
||||
import { Routes } from '../../../navigation'
|
||||
import { navigate } from '../../../navigation/NavigationService'
|
||||
import { useUserData } from '../../../providers/UserDataProvider'
|
||||
import { Palette } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import CardContainer from './CardContainer'
|
||||
const BackTracks = () => {
|
||||
const { userPlaybacks } = useUserData();
|
||||
const { isWeb } = useLayoutType();
|
||||
const items = Array.isArray(userPlaybacks)
|
||||
? userPlaybacks.slice(0, isWeb ? 2 : 3)
|
||||
: [];
|
||||
const { width: screenWidth } = useWindowDimensions();
|
||||
const [containerWidth, setContainerWidth] = useState(screenWidth);
|
||||
const numColumns = isWeb ? 2 : 3;
|
||||
const gap = 8;
|
||||
const itemWidth = Math.max(
|
||||
0,
|
||||
Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns)
|
||||
);
|
||||
const { userPlaybacks } = useUserData()
|
||||
const { isWeb } = useLayoutType()
|
||||
const items = Array.isArray(userPlaybacks) ? userPlaybacks.slice(0, isWeb ? 2 : 3) : []
|
||||
const { width: screenWidth } = useWindowDimensions()
|
||||
const [containerWidth, setContainerWidth] = useState(screenWidth)
|
||||
const numColumns = isWeb ? 2 : 3
|
||||
const gap = 8
|
||||
const itemWidth = Math.max(0, Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns))
|
||||
|
||||
const openPlaybackPicker = useCallback(() => {
|
||||
SheetManager.show("PlaybackPicker");
|
||||
}, []);
|
||||
SheetManager.show('PlaybackPicker')
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<CardContainer
|
||||
label="Mes Playback"
|
||||
onPress={() =>
|
||||
navigate(Routes.AllMyList, {
|
||||
title: "Mes playback",
|
||||
scope: "playback",
|
||||
title: 'Mes playback',
|
||||
scope: 'playback',
|
||||
liked: false,
|
||||
})
|
||||
}
|
||||
@@ -58,15 +46,11 @@ const BackTracks = () => {
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => (
|
||||
<View style={{ width: itemWidth }} key={item.id}>
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
navigate(Routes.Playbacks, { projectId: item.id })
|
||||
}
|
||||
>
|
||||
<Pressable onPress={() => navigate(Routes.Playbacks, { projectId: item.id })}>
|
||||
<Image
|
||||
source={{ uri: item?.thumbnailUrl || item?.coverUrl || "" }}
|
||||
source={{ uri: item?.thumbnailUrl || item?.coverUrl || '' }}
|
||||
style={{
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
height: Math.round((itemWidth * 16) / 9),
|
||||
borderRadius: 10,
|
||||
}}
|
||||
@@ -76,10 +60,10 @@ const BackTracks = () => {
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<View style={{ flexDirection: "column", gap: 10 }}>
|
||||
<View style={{ flexDirection: 'column', gap: 10 }}>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
color: Palette.white,
|
||||
fontSize: 16,
|
||||
@@ -96,7 +80,7 @@ const BackTracks = () => {
|
||||
)}
|
||||
</View>
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default BackTracks;
|
||||
export default BackTracks
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React from "react";
|
||||
import { Image, Pressable, StyleSheet, Text, View } from "react-native";
|
||||
import { icons } from "../../../assets";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
const CardContainer = ({ children, label = "", onPress, onPressPlus }) => {
|
||||
import React from 'react'
|
||||
import { Image, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { icons } from '../../../assets'
|
||||
import { Palette, Style } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
const CardContainer = ({ children, label = '', onPress, onPressPlus }) => {
|
||||
return (
|
||||
<View style={{ gap: 12 }}>
|
||||
<View style={{ ...Style.containerSpaceBetween }}>
|
||||
<Text style={styles.label}>{label}</Text>
|
||||
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 20 }}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 20 }}>
|
||||
<Pressable onPress={onPressPlus}>
|
||||
<Image source={icons.add} style={{ width: 15, height: 15 }} />
|
||||
</Pressable>
|
||||
@@ -20,10 +20,10 @@ const CardContainer = ({ children, label = "", onPress, onPressPlus }) => {
|
||||
</View>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CardContainer;
|
||||
export default CardContainer
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
label: {
|
||||
@@ -36,4 +36,4 @@ const styles = StyleSheet.create({
|
||||
color: Palette.gray,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { View, Text, Image } from "react-native";
|
||||
import React from "react";
|
||||
import CardContainer from "./CardContainer";
|
||||
import { Style } from "../../../styles";
|
||||
import { img } from "../../../assets";
|
||||
import { View, Text, Image } from 'react-native'
|
||||
import React from 'react'
|
||||
import CardContainer from './CardContainer'
|
||||
import { Style } from '../../../styles'
|
||||
import { img } from '../../../assets'
|
||||
|
||||
const LikedClips = () => {
|
||||
return (
|
||||
@@ -12,13 +12,13 @@ const LikedClips = () => {
|
||||
<View style={{ flex: 1 }} key={index}>
|
||||
<Image
|
||||
source={img.placeholder3}
|
||||
style={{ width: "100%", height: 172, borderRadius: 10 }}
|
||||
style={{ width: '100%', height: 172, borderRadius: 10 }}
|
||||
/>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default LikedClips;
|
||||
export default LikedClips
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { Image as ExpoImage } from 'expo-image'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import {
|
||||
FlatList,
|
||||
Pressable,
|
||||
@@ -7,62 +7,49 @@ import {
|
||||
Text,
|
||||
useWindowDimensions,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { img } from "../../../assets";
|
||||
import GradientButton from "../../../components/GradientButton";
|
||||
import useLayoutType from "../../../hooks/useLayoutType";
|
||||
import useNavigateToMusicDetails from "../../../hooks/useNavigateToMusicDetails";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import CardContainer from "./CardContainer";
|
||||
} from 'react-native'
|
||||
import { img } from '../../../assets'
|
||||
import GradientButton from '../../../components/GradientButton'
|
||||
import useLayoutType from '../../../hooks/useLayoutType'
|
||||
import useNavigateToMusicDetails from '../../../hooks/useNavigateToMusicDetails'
|
||||
import { Routes } from '../../../navigation'
|
||||
import { navigate } from '../../../navigation/NavigationService'
|
||||
import { useUser } from '../../../providers/UserDataProvider'
|
||||
import { Palette } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import CardContainer from './CardContainer'
|
||||
const LikedMusic = () => {
|
||||
const { userLikedProjects = [] } = useUser();
|
||||
const items = Array.isArray(userLikedProjects)
|
||||
? userLikedProjects.slice(0, 3)
|
||||
: [];
|
||||
const { width: screenWidth } = useWindowDimensions();
|
||||
const { isWeb } = useLayoutType();
|
||||
const [containerWidth, setContainerWidth] = useState(screenWidth);
|
||||
const numColumns = isWeb ? 2 : 3;
|
||||
const gap = 8;
|
||||
const itemWidth = Math.max(
|
||||
0,
|
||||
Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns)
|
||||
);
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails();
|
||||
const { userLikedProjects = [] } = useUser()
|
||||
const items = Array.isArray(userLikedProjects) ? userLikedProjects.slice(0, 3) : []
|
||||
const { width: screenWidth } = useWindowDimensions()
|
||||
const { isWeb } = useLayoutType()
|
||||
const [containerWidth, setContainerWidth] = useState(screenWidth)
|
||||
const numColumns = isWeb ? 2 : 3
|
||||
const gap = 8
|
||||
const itemWidth = Math.max(0, Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns))
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails()
|
||||
const resolveCoverUri = useCallback((project) => {
|
||||
if (!project) return null;
|
||||
const isValid = (value) =>
|
||||
typeof value === "string" && value.trim().length > 0;
|
||||
if (!project) return null
|
||||
const isValid = (value) => typeof value === 'string' && value.trim().length > 0
|
||||
if (isValid(project?.coverUrl)) {
|
||||
return project.coverUrl;
|
||||
return project.coverUrl
|
||||
}
|
||||
const cover = project?.cover || {};
|
||||
const coverCandidates = [
|
||||
cover?.result,
|
||||
cover?.finalUrl,
|
||||
cover?.generatedBackground,
|
||||
];
|
||||
const cover = project?.cover || {}
|
||||
const coverCandidates = [cover?.result, cover?.finalUrl, cover?.generatedBackground]
|
||||
if (Array.isArray(cover?.options)) {
|
||||
coverCandidates.push(
|
||||
...cover.options.flatMap((option) => [
|
||||
option?.finalUrl,
|
||||
option?.generatedUrl,
|
||||
])
|
||||
);
|
||||
...cover.options.flatMap((option) => [option?.finalUrl, option?.generatedUrl])
|
||||
)
|
||||
}
|
||||
return coverCandidates.find(isValid) || null;
|
||||
}, []);
|
||||
return coverCandidates.find(isValid) || null
|
||||
}, [])
|
||||
return (
|
||||
<CardContainer
|
||||
label="Musiques likées"
|
||||
onPress={() =>
|
||||
navigate(Routes.AllMyList, {
|
||||
title: "Musiques likées",
|
||||
scope: "music",
|
||||
title: 'Musiques likées',
|
||||
scope: 'music',
|
||||
liked: true,
|
||||
})
|
||||
}
|
||||
@@ -97,7 +84,7 @@ const LikedMusic = () => {
|
||||
contentFit="cover"
|
||||
transition={100}
|
||||
style={{
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
height: itemWidth,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
@@ -106,7 +93,7 @@ const LikedMusic = () => {
|
||||
<RNImage
|
||||
source={img.placeholder3}
|
||||
style={{
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
height: itemWidth,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
@@ -116,10 +103,10 @@ const LikedMusic = () => {
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<View style={{ flexDirection: "column", gap: 10 }}>
|
||||
<View style={{ flexDirection: 'column', gap: 10 }}>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
color: Palette.white,
|
||||
fontSize: 16,
|
||||
@@ -135,7 +122,7 @@ const LikedMusic = () => {
|
||||
</View>
|
||||
)}
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default LikedMusic;
|
||||
export default LikedMusic
|
||||
|
||||
@@ -1,41 +1,29 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
Pressable,
|
||||
Text,
|
||||
View,
|
||||
useWindowDimensions,
|
||||
} from "react-native";
|
||||
import GradientButton from "../../../components/GradientButton";
|
||||
import useLayoutType from "../../../hooks/useLayoutType";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUserData } from "../../../providers/UserDataProvider";
|
||||
import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import CardContainer from "./CardContainer";
|
||||
import React, { useState } from 'react'
|
||||
import { FlatList, Image, Pressable, Text, View, useWindowDimensions } from 'react-native'
|
||||
import GradientButton from '../../../components/GradientButton'
|
||||
import useLayoutType from '../../../hooks/useLayoutType'
|
||||
import { Routes } from '../../../navigation'
|
||||
import { navigate } from '../../../navigation/NavigationService'
|
||||
import { useUserData } from '../../../providers/UserDataProvider'
|
||||
import { Palette } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import CardContainer from './CardContainer'
|
||||
const LikedPlayback = () => {
|
||||
const { isWeb } = useLayoutType();
|
||||
const { userLikedPlaybacks } = useUserData();
|
||||
const items = Array.isArray(userLikedPlaybacks)
|
||||
? userLikedPlaybacks.slice(0, isWeb ? 2 : 3)
|
||||
: [];
|
||||
const { width: screenWidth } = useWindowDimensions();
|
||||
const [containerWidth, setContainerWidth] = useState(screenWidth);
|
||||
const numColumns = isWeb ? 2 : 3;
|
||||
const gap = 8;
|
||||
const itemWidth = Math.max(
|
||||
0,
|
||||
Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns)
|
||||
);
|
||||
const { isWeb } = useLayoutType()
|
||||
const { userLikedPlaybacks } = useUserData()
|
||||
const items = Array.isArray(userLikedPlaybacks) ? userLikedPlaybacks.slice(0, isWeb ? 2 : 3) : []
|
||||
const { width: screenWidth } = useWindowDimensions()
|
||||
const [containerWidth, setContainerWidth] = useState(screenWidth)
|
||||
const numColumns = isWeb ? 2 : 3
|
||||
const gap = 8
|
||||
const itemWidth = Math.max(0, Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns))
|
||||
return (
|
||||
<CardContainer
|
||||
label="Playback likés"
|
||||
onPress={() =>
|
||||
navigate(Routes.AllMyList, {
|
||||
title: "Playback likés",
|
||||
scope: "playback",
|
||||
title: 'Playback likés',
|
||||
scope: 'playback',
|
||||
liked: true,
|
||||
})
|
||||
}
|
||||
@@ -52,15 +40,11 @@ const LikedPlayback = () => {
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => (
|
||||
<View style={{ width: itemWidth }} key={item.id}>
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
navigate(Routes.Playbacks, { projectId: item.id })
|
||||
}
|
||||
>
|
||||
<Pressable onPress={() => navigate(Routes.Playbacks, { projectId: item.id })}>
|
||||
<Image
|
||||
source={{ uri: item?.thumbnailUrl || item?.coverUrl || "" }}
|
||||
source={{ uri: item?.thumbnailUrl || item?.coverUrl || '' }}
|
||||
style={{
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
height: Math.round((itemWidth * 16) / 9),
|
||||
borderRadius: 10,
|
||||
}}
|
||||
@@ -70,10 +54,10 @@ const LikedPlayback = () => {
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<View style={{ flexDirection: "column", gap: 10 }}>
|
||||
<View style={{ flexDirection: 'column', gap: 10 }}>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
color: Palette.white,
|
||||
fontSize: 16,
|
||||
@@ -90,7 +74,7 @@ const LikedPlayback = () => {
|
||||
)}
|
||||
</View>
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default LikedPlayback;
|
||||
export default LikedPlayback
|
||||
|
||||
@@ -1,95 +1,88 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Dimensions,
|
||||
Pressable,
|
||||
Image as RNImage,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { responsiveWidth } from "react-native-responsive-dimensions";
|
||||
import { useGlobal } from "reactn";
|
||||
import { icons, img } from "../../../assets";
|
||||
import PressableScale from "../../../components/PressableScale";
|
||||
import { LIKE_TARGET, toggleProjectLike } from "../../../utils/likes";
|
||||
import { ensureAuthenticated } from "../../../utils/authRedirect";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { size } from "../../../styles/Style";
|
||||
import { BlurView } from 'expo-blur'
|
||||
import { Image as ExpoImage } from 'expo-image'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { Dimensions, Pressable, Image as RNImage, StyleSheet, Text, View } from 'react-native'
|
||||
import { responsiveWidth } from 'react-native-responsive-dimensions'
|
||||
import { useGlobal } from 'reactn'
|
||||
import { icons, img } from '../../../assets'
|
||||
import PressableScale from '../../../components/PressableScale'
|
||||
import { LIKE_TARGET, toggleProjectLike } from '../../../utils/likes'
|
||||
import { ensureAuthenticated } from '../../../utils/authRedirect'
|
||||
import { Palette, Style } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import { size } from '../../../styles/Style'
|
||||
|
||||
const MusicCard = ({
|
||||
onPress,
|
||||
onPressMore,
|
||||
title = "Sans titre",
|
||||
subtitle = "MusicLand",
|
||||
title = 'Sans titre',
|
||||
subtitle = 'MusicLand',
|
||||
imageUri = null,
|
||||
projectId = null,
|
||||
likedBy = [],
|
||||
likeTarget = LIKE_TARGET.SONG,
|
||||
}) => {
|
||||
const [currentUID] = useGlobal("currentUID");
|
||||
const [selected, setSelected] = useState(false);
|
||||
const [layout, setLayout] = useState(null);
|
||||
const [currentUID] = useGlobal('currentUID')
|
||||
const [selected, setSelected] = useState(false)
|
||||
const [layout, setLayout] = useState(null)
|
||||
const [menuPos, setMenuPos] = useState({
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
});
|
||||
const cardRef = useRef(null);
|
||||
const moreButtonRef = useRef(null);
|
||||
})
|
||||
const cardRef = useRef(null)
|
||||
const moreButtonRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (layout) {
|
||||
const top = (layout?.y || 0) + 45;
|
||||
setMenuPos((prev) => ({ ...prev, top }));
|
||||
const top = (layout?.y || 0) + 45
|
||||
setMenuPos((prev) => ({ ...prev, top }))
|
||||
}
|
||||
}, [layout]);
|
||||
}, [layout])
|
||||
|
||||
useEffect(() => {
|
||||
if (Array.isArray(likedBy) && currentUID) {
|
||||
setSelected(likedBy.includes(currentUID));
|
||||
setSelected(likedBy.includes(currentUID))
|
||||
}
|
||||
}, [JSON.stringify(likedBy), currentUID]);
|
||||
}, [JSON.stringify(likedBy), currentUID])
|
||||
|
||||
const toggleLike = async () => {
|
||||
if (!projectId) return;
|
||||
if (!ensureAuthenticated(currentUID)) return;
|
||||
const next = !selected;
|
||||
setSelected(next);
|
||||
if (!projectId) return
|
||||
if (!ensureAuthenticated(currentUID)) return
|
||||
const next = !selected
|
||||
setSelected(next)
|
||||
try {
|
||||
await toggleProjectLike({
|
||||
projectId,
|
||||
target: likeTarget,
|
||||
currentUID,
|
||||
next,
|
||||
});
|
||||
})
|
||||
} catch (e) {
|
||||
// rollback on failure
|
||||
setSelected(!next);
|
||||
setSelected(!next)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const onPressMenu = () => {
|
||||
const computeAnchor = (x = 0, y = 0, width = 0, height = 0) => {
|
||||
const windowWidth = Dimensions.get("window").width || 0;
|
||||
const top = (y || 0) + (height || 0) + 8;
|
||||
const right = Math.max(0, windowWidth - ((x || 0) + (width || 0)));
|
||||
const left = Math.max(0, x || 0);
|
||||
const anchor = { top, right, left, width, height };
|
||||
setMenuPos(anchor);
|
||||
onPressMore?.(anchor);
|
||||
};
|
||||
const windowWidth = Dimensions.get('window').width || 0
|
||||
const top = (y || 0) + (height || 0) + 8
|
||||
const right = Math.max(0, windowWidth - ((x || 0) + (width || 0)))
|
||||
const left = Math.max(0, x || 0)
|
||||
const anchor = { top, right, left, width, height }
|
||||
setMenuPos(anchor)
|
||||
onPressMore?.(anchor)
|
||||
}
|
||||
|
||||
if (moreButtonRef?.current?.measureInWindow) {
|
||||
try {
|
||||
moreButtonRef.current.measureInWindow((x, y, width, height) => {
|
||||
computeAnchor(x, y, width, height);
|
||||
});
|
||||
return;
|
||||
computeAnchor(x, y, width, height)
|
||||
})
|
||||
return
|
||||
} catch (e) {
|
||||
// fallback to card measurement below
|
||||
}
|
||||
@@ -99,15 +92,15 @@ const MusicCard = ({
|
||||
if (cardRef?.current?.measureInWindow) {
|
||||
try {
|
||||
cardRef.current.measureInWindow((x, y, width, height) => {
|
||||
computeAnchor(x, y, width, height);
|
||||
});
|
||||
return;
|
||||
computeAnchor(x, y, width, height)
|
||||
})
|
||||
return
|
||||
} catch (e) {
|
||||
// fallback to relative layout position
|
||||
}
|
||||
}
|
||||
onPressMore?.(menuPos);
|
||||
};
|
||||
onPressMore?.(menuPos)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -130,10 +123,7 @@ const MusicCard = ({
|
||||
style={{ ...size({ size: 60 }), borderRadius: 12 }}
|
||||
/>
|
||||
) : (
|
||||
<RNImage
|
||||
source={img.placeholder}
|
||||
style={{ ...size({ size: 60 }), borderRadius: 12 }}
|
||||
/>
|
||||
<RNImage source={img.placeholder} style={{ ...size({ size: 60 }), borderRadius: 12 }} />
|
||||
)}
|
||||
<View style={styles.blurContainer}>
|
||||
<BlurView
|
||||
@@ -149,9 +139,9 @@ const MusicCard = ({
|
||||
>
|
||||
<View style={{ gap: 3, flexShrink: 1, paddingVertical: 11 }}>
|
||||
<Text numberOfLines={2} style={styles.title}>
|
||||
{title || "Sans titre"}
|
||||
{title || 'Sans titre'}
|
||||
</Text>
|
||||
<Text style={styles.subTitle}>{subtitle || "MusicLand"}</Text>
|
||||
<Text style={styles.subTitle}>{subtitle || 'MusicLand'}</Text>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
@@ -187,17 +177,17 @@ const MusicCard = ({
|
||||
/>
|
||||
)} */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default MusicCard;
|
||||
export default MusicCard
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
blurContainer: {
|
||||
borderRadius: 12,
|
||||
overflow: "hidden",
|
||||
overflow: 'hidden',
|
||||
flex: 1,
|
||||
height: "100%",
|
||||
height: '100%',
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
@@ -214,4 +204,4 @@ const styles = StyleSheet.create({
|
||||
filterContainer: {
|
||||
backgroundColor: Palette.tran,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { View, Text, Image } from "react-native";
|
||||
import React from "react";
|
||||
import CardContainer from "./CardContainer";
|
||||
import { Style } from "../../../styles";
|
||||
import { img } from "../../../assets";
|
||||
import { View, Text, Image } from 'react-native'
|
||||
import React from 'react'
|
||||
import CardContainer from './CardContainer'
|
||||
import { Style } from '../../../styles'
|
||||
import { img } from '../../../assets'
|
||||
|
||||
const MyClips = () => {
|
||||
return (
|
||||
@@ -12,13 +12,13 @@ const MyClips = () => {
|
||||
<View style={{ flex: 1 }} key={index}>
|
||||
<Image
|
||||
source={img.placeholder3}
|
||||
style={{ width: "100%", height: 172, borderRadius: 10 }}
|
||||
style={{ width: '100%', height: 172, borderRadius: 10 }}
|
||||
/>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default MyClips;
|
||||
export default MyClips
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
import React, { useState } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { useGlobal } from "reactn";
|
||||
import GradientButton from "../../../components/GradientButton";
|
||||
import MoreMenu from "../../../components/MoreMenu";
|
||||
import { projectsRef } from "../../../config/firebase";
|
||||
import useNavigateToMusicDetails from "../../../hooks/useNavigateToMusicDetails";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../../utils/likes";
|
||||
import CardContainer from "./CardContainer";
|
||||
import MusicCard from "./MusicCard";
|
||||
import React, { useState } from 'react'
|
||||
import { Text, View } from 'react-native'
|
||||
import { SheetManager } from 'react-native-actions-sheet'
|
||||
import { useGlobal } from 'reactn'
|
||||
import GradientButton from '../../../components/GradientButton'
|
||||
import MoreMenu from '../../../components/MoreMenu'
|
||||
import { projectsRef } from '../../../config/firebase'
|
||||
import useNavigateToMusicDetails from '../../../hooks/useNavigateToMusicDetails'
|
||||
import { Routes } from '../../../navigation'
|
||||
import { navigate } from '../../../navigation/NavigationService'
|
||||
import { useUser } from '../../../providers/UserDataProvider'
|
||||
import { Palette } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import { getProjectLikes, LIKE_TARGET } from '../../../utils/likes'
|
||||
import CardContainer from './CardContainer'
|
||||
import MusicCard from './MusicCard'
|
||||
const MyMusic = () => {
|
||||
const { userProjects = [] } = useUser();
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const projects = Array.isArray(userProjects) ? userProjects.slice(0, 3) : [];
|
||||
const hasProjects = projects.length > 0;
|
||||
const { userProjects = [] } = useUser()
|
||||
const [menuPosition, setMenuPosition] = useState(null)
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null)
|
||||
const projects = Array.isArray(userProjects) ? userProjects.slice(0, 3) : []
|
||||
const hasProjects = projects.length > 0
|
||||
|
||||
const [, setTooltip] = useGlobal("_tooltip");
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails();
|
||||
const [, setTooltip] = useGlobal('_tooltip')
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails()
|
||||
|
||||
return (
|
||||
<CardContainer
|
||||
label="Mes musiques"
|
||||
onPress={() =>
|
||||
navigate(Routes.AllMyList, {
|
||||
title: "Mes musiques",
|
||||
scope: "music",
|
||||
title: 'Mes musiques',
|
||||
scope: 'music',
|
||||
liked: false,
|
||||
})
|
||||
}
|
||||
@@ -57,12 +57,9 @@ const MyMusic = () => {
|
||||
})
|
||||
}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null)
|
||||
);
|
||||
setSelectedProjectId(p.id)
|
||||
setMenuPosition(posTop)
|
||||
setShowMenu((prev) => !prev || posTop?.top !== (menuPosition?.top ?? null))
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -75,26 +72,25 @@ const MyMusic = () => {
|
||||
projectId={selectedProjectId}
|
||||
extraItems={[
|
||||
{
|
||||
label: "Supprimer",
|
||||
label: 'Supprimer',
|
||||
onPress: () =>
|
||||
SheetManager.show("Delete", {
|
||||
SheetManager.show('Delete', {
|
||||
payload: {
|
||||
title: "Supprimer le projet",
|
||||
message:
|
||||
"Cette action supprimera définitivement ce projet.",
|
||||
title: 'Supprimer le projet',
|
||||
message: 'Cette action supprimera définitivement ce projet.',
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
if (!selectedProjectId) return;
|
||||
await projectsRef.doc(selectedProjectId).delete();
|
||||
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',
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -104,10 +100,10 @@ const MyMusic = () => {
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{ flexDirection: "column", gap: 10 }}>
|
||||
<View style={{ flexDirection: 'column', gap: 10 }}>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
color: Palette.white,
|
||||
fontSize: 16,
|
||||
@@ -123,7 +119,7 @@ const MyMusic = () => {
|
||||
</View>
|
||||
)}
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default MyMusic;
|
||||
export default MyMusic
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React from "react";
|
||||
import { Image, Platform, Pressable, Text, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { icons } from "../../../assets";
|
||||
import GradientButton from "../../../components/GradientButton";
|
||||
import useLayoutType from "../../../hooks/useLayoutType";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import Style, { size } from "../../../styles/Style";
|
||||
import CardContainer from "./CardContainer";
|
||||
import { BlurView } from 'expo-blur'
|
||||
import React from 'react'
|
||||
import { Image, Platform, Pressable, Text, View } from 'react-native'
|
||||
import { SheetManager } from 'react-native-actions-sheet'
|
||||
import { icons } from '../../../assets'
|
||||
import GradientButton from '../../../components/GradientButton'
|
||||
import useLayoutType from '../../../hooks/useLayoutType'
|
||||
import { Routes } from '../../../navigation'
|
||||
import { navigate } from '../../../navigation/NavigationService'
|
||||
import { useUser } from '../../../providers/UserDataProvider'
|
||||
import { Palette } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import Style, { size } from '../../../styles/Style'
|
||||
import CardContainer from './CardContainer'
|
||||
const MyPlaylist = () => {
|
||||
const { userPlaylists = [] } = useUser();
|
||||
const playlists = Array.isArray(userPlaylists)
|
||||
? userPlaylists.slice(0, 2)
|
||||
: [];
|
||||
const { isWeb } = useLayoutType();
|
||||
const hasPlaylists = playlists.length > 0;
|
||||
const { userPlaylists = [] } = useUser()
|
||||
const playlists = Array.isArray(userPlaylists) ? userPlaylists.slice(0, 2) : []
|
||||
const { isWeb } = useLayoutType()
|
||||
const hasPlaylists = playlists.length > 0
|
||||
return (
|
||||
<CardContainer
|
||||
label="Mes Playlists"
|
||||
onPress={() => navigate(Routes.AllMyPlaylist)}
|
||||
onPressPlus={() =>
|
||||
SheetManager.show("Playlist", {
|
||||
SheetManager.show('Playlist', {
|
||||
payload: { startAtCreate: true },
|
||||
})
|
||||
}
|
||||
@@ -34,18 +32,18 @@ const MyPlaylist = () => {
|
||||
playlists.map((item) => (
|
||||
<Pressable
|
||||
key={item.id}
|
||||
style={{ borderRadius: 12, overflow: "hidden" }}
|
||||
style={{ borderRadius: 12, overflow: 'hidden' }}
|
||||
onPress={() => {
|
||||
console.log("isWeb", isWeb);
|
||||
console.log('isWeb', isWeb)
|
||||
if (isWeb) {
|
||||
navigate(Routes.AllMyPlaylist, { playListId: item.id });
|
||||
navigate(Routes.AllMyPlaylist, { playListId: item.id })
|
||||
} else {
|
||||
navigate(Routes.PlaylistDetails, { playlistId: item.id });
|
||||
navigate(Routes.PlaylistDetails, { playlistId: item.id })
|
||||
}
|
||||
}}
|
||||
>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 10 : 20}
|
||||
intensity={Platform.OS !== 'ios' ? 10 : 20}
|
||||
style={{
|
||||
...Style.containerSpaceBetween,
|
||||
minHeight: 59,
|
||||
@@ -66,13 +64,13 @@ const MyPlaylist = () => {
|
||||
flexShrink: 1,
|
||||
}}
|
||||
>
|
||||
{item?.name || "Sans nom"}
|
||||
{item?.name || 'Sans nom'}
|
||||
</Text>
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
style={{
|
||||
...size({ size: 15 }),
|
||||
transform: [{ rotate: "-90deg" }],
|
||||
transform: [{ rotate: '-90deg' }],
|
||||
}}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
@@ -80,10 +78,10 @@ const MyPlaylist = () => {
|
||||
</Pressable>
|
||||
))
|
||||
) : (
|
||||
<View style={{ flexDirection: "column", gap: 10 }}>
|
||||
<View style={{ flexDirection: 'column', gap: 10 }}>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
color: Palette.white,
|
||||
fontSize: 16,
|
||||
@@ -94,7 +92,7 @@ const MyPlaylist = () => {
|
||||
<GradientButton
|
||||
containerStyle={{ padding: 2 }}
|
||||
onPress={() =>
|
||||
SheetManager.show("Playlist", {
|
||||
SheetManager.show('Playlist', {
|
||||
payload: { startAtCreate: true },
|
||||
})
|
||||
}
|
||||
@@ -104,7 +102,7 @@ const MyPlaylist = () => {
|
||||
)}
|
||||
</View>
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default MyPlaylist;
|
||||
export default MyPlaylist
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { View, Text, Pressable, StyleSheet, Platform } from "react-native";
|
||||
import React from "react";
|
||||
import SearchBar from "../../../components/SearchBar";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import BorderGradient from "../../../components/BorderGradient/BorderGradient";
|
||||
import { BlurView } from "expo-blur";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { View, Text, Pressable, StyleSheet, Platform } from 'react-native'
|
||||
import React from 'react'
|
||||
import SearchBar from '../../../components/SearchBar'
|
||||
import { Palette, Style } from '../../../styles'
|
||||
import BorderGradient from '../../../components/BorderGradient/BorderGradient'
|
||||
import { BlurView } from 'expo-blur'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
|
||||
const ResearchHeader = ({
|
||||
onPress,
|
||||
selected,
|
||||
searchValue = "",
|
||||
searchValue = '',
|
||||
onChangeSearch = () => {},
|
||||
showSearchBar = true,
|
||||
autoFocusSearch = true,
|
||||
@@ -31,14 +31,11 @@ const ResearchHeader = ({
|
||||
gap: 6,
|
||||
}}
|
||||
>
|
||||
{["Musiques", "Playback", "Profils"].map((item, index) => (
|
||||
{['Musiques', 'Playback', 'Profils'].map((item, index) => (
|
||||
<Pressable key={index} onPress={() => onPress(item)}>
|
||||
<BorderGradient
|
||||
gradientProps={{
|
||||
colors:
|
||||
selected === item
|
||||
? ["#F94697", "#7023F7"]
|
||||
: [Palette.tran, Palette.tran],
|
||||
colors: selected === item ? ['#F94697', '#7023F7'] : [Palette.tran, Palette.tran],
|
||||
locations: [0, 1],
|
||||
start: { x: 0, y: 0 },
|
||||
end: { x: 1, y: 0 },
|
||||
@@ -46,10 +43,7 @@ const ResearchHeader = ({
|
||||
style={styles.borderGradient}
|
||||
/>
|
||||
<View style={styles.blurContainer}>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 10 : 20}
|
||||
style={styles.blurView}
|
||||
>
|
||||
<BlurView intensity={Platform.OS !== 'ios' ? 10 : 20} style={styles.blurView}>
|
||||
<Text style={styles.menu}>{item}</Text>
|
||||
</BlurView>
|
||||
</View>
|
||||
@@ -57,10 +51,10 @@ const ResearchHeader = ({
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default ResearchHeader;
|
||||
export default ResearchHeader
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
menu: {
|
||||
@@ -72,21 +66,21 @@ const styles = StyleSheet.create({
|
||||
borderWidth: 1,
|
||||
borderRadius: 100,
|
||||
height: 30,
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
zIndex: 1,
|
||||
width: "100%",
|
||||
width: '100%',
|
||||
},
|
||||
blurContainer: {
|
||||
height: 30,
|
||||
zIndex: -1,
|
||||
borderRadius: 100,
|
||||
overflow: "hidden",
|
||||
overflow: 'hidden',
|
||||
backgroundColor: Palette.glass,
|
||||
},
|
||||
blurView: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
justifyContent: "center",
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import { Pressable, ScrollView, Text, View } from "react-native";
|
||||
import MoreMenu from "../../../components/MoreMenu";
|
||||
import ProfilePicture from "../../../components/ProfilePicture";
|
||||
import useNavigateToMusicDetails from "../../../hooks/useNavigateToMusicDetails";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { getArtistDisplayName } from "../../../utils/artistName";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../../utils/likes";
|
||||
import CreateLyricsHeader from "../../Writing/components/CreateLyricsHeader";
|
||||
import MusicCard from "./MusicCard";
|
||||
import { defaultAvatar } from "../../../data/data";
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Pressable, ScrollView, Text, View } from 'react-native'
|
||||
import MoreMenu from '../../../components/MoreMenu'
|
||||
import ProfilePicture from '../../../components/ProfilePicture'
|
||||
import useNavigateToMusicDetails from '../../../hooks/useNavigateToMusicDetails'
|
||||
import { Routes } from '../../../navigation'
|
||||
import { navigate } from '../../../navigation/NavigationService'
|
||||
import { Palette, Style } from '../../../styles'
|
||||
import { FONT_FAMILY } from '../../../styles/Fonts'
|
||||
import { getArtistDisplayName } from '../../../utils/artistName'
|
||||
import { getProjectLikes, LIKE_TARGET } from '../../../utils/likes'
|
||||
import CreateLyricsHeader from '../../Writing/components/CreateLyricsHeader'
|
||||
import MusicCard from './MusicCard'
|
||||
import { defaultAvatar } from '../../../data/data'
|
||||
|
||||
const EmptyText = ({ text }) => (
|
||||
<View style={{ flex: 1, alignItems: "center", paddingVertical: 16 }}>
|
||||
<View style={{ flex: 1, alignItems: 'center', paddingVertical: 16 }}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
@@ -26,7 +26,7 @@ const EmptyText = ({ text }) => (
|
||||
{text}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
)
|
||||
|
||||
const SearchResultsList = ({
|
||||
selected,
|
||||
@@ -40,105 +40,89 @@ const SearchResultsList = ({
|
||||
contentContainerStyle,
|
||||
style,
|
||||
}) => {
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const [menuPosition, setMenuPosition] = useState(null)
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null)
|
||||
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails();
|
||||
const navigateToMusicDetails = useNavigateToMusicDetails()
|
||||
|
||||
const resolveCoverUri = useCallback(
|
||||
(project, { preferThumbnail = false } = {}) => {
|
||||
const isValid = (value) =>
|
||||
typeof value === "string" && value.trim().length > 0;
|
||||
if (!project) {
|
||||
return null;
|
||||
const resolveCoverUri = useCallback((project, { preferThumbnail = false } = {}) => {
|
||||
const isValid = (value) => typeof value === 'string' && value.trim().length > 0
|
||||
if (!project) {
|
||||
return null
|
||||
}
|
||||
|
||||
const cover = project?.cover || {}
|
||||
const thumbnailCandidates = [project?.thumbnailUrl, project?.songThumbnailUrl].filter(isValid)
|
||||
|
||||
if (preferThumbnail) {
|
||||
const preferredThumbnail = thumbnailCandidates.find(isValid)
|
||||
if (preferredThumbnail) {
|
||||
return preferredThumbnail
|
||||
}
|
||||
}
|
||||
|
||||
const cover = project?.cover || {};
|
||||
const thumbnailCandidates = [
|
||||
project?.thumbnailUrl,
|
||||
project?.songThumbnailUrl,
|
||||
].filter(isValid);
|
||||
if (isValid(project?.coverUrl)) {
|
||||
return project.coverUrl
|
||||
}
|
||||
|
||||
if (preferThumbnail) {
|
||||
const preferredThumbnail = thumbnailCandidates.find(isValid);
|
||||
if (preferredThumbnail) {
|
||||
return preferredThumbnail;
|
||||
}
|
||||
}
|
||||
const coverCandidates = [cover?.result, cover?.finalUrl, cover?.generatedBackground]
|
||||
|
||||
if (isValid(project?.coverUrl)) {
|
||||
return project.coverUrl;
|
||||
}
|
||||
if (Array.isArray(cover?.options)) {
|
||||
coverCandidates.push(
|
||||
...cover.options.flatMap((option) => [option?.finalUrl, option?.generatedUrl])
|
||||
)
|
||||
}
|
||||
|
||||
const coverCandidates = [
|
||||
cover?.result,
|
||||
cover?.finalUrl,
|
||||
cover?.generatedBackground,
|
||||
];
|
||||
|
||||
if (Array.isArray(cover?.options)) {
|
||||
coverCandidates.push(
|
||||
...cover.options.flatMap((option) => [
|
||||
option?.finalUrl,
|
||||
option?.generatedUrl,
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
return coverCandidates.find(isValid) || null;
|
||||
},
|
||||
[],
|
||||
);
|
||||
return coverCandidates.find(isValid) || null
|
||||
}, [])
|
||||
|
||||
const handleMusicPress = (project) => {
|
||||
const didNavigate = navigateToMusicDetails({
|
||||
projectId: project?.id,
|
||||
songUrl: project?.songUrl,
|
||||
project,
|
||||
});
|
||||
})
|
||||
|
||||
if (didNavigate) {
|
||||
onResultSelected?.();
|
||||
onResultSelected?.()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handlePlaybackPress = (project) => {
|
||||
if (!project?.id) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
navigate(Routes.Playbacks, { projectId: project.id });
|
||||
onResultSelected?.();
|
||||
};
|
||||
navigate(Routes.Playbacks, { projectId: project.id })
|
||||
onResultSelected?.()
|
||||
}
|
||||
|
||||
const handleProfilePress = (userId) => {
|
||||
navigate(Routes.SingerProfile, { userId });
|
||||
onResultSelected?.();
|
||||
};
|
||||
navigate(Routes.SingerProfile, { userId })
|
||||
onResultSelected?.()
|
||||
}
|
||||
|
||||
const musicItems = useMemo(() => {
|
||||
if (!Array.isArray(musics)) {
|
||||
return [];
|
||||
return []
|
||||
}
|
||||
|
||||
if (selected === "Musiques") {
|
||||
return musics;
|
||||
if (selected === 'Musiques') {
|
||||
return musics
|
||||
}
|
||||
|
||||
return musics.filter((project) => project?.hasPlayback !== true);
|
||||
}, [musics, selected]);
|
||||
return musics.filter((project) => project?.hasPlayback !== true)
|
||||
}, [musics, selected])
|
||||
|
||||
const shouldShowMusics =
|
||||
(!selected && (musicItems.length > 0 || musicsLoading)) ||
|
||||
selected === "Musiques";
|
||||
(!selected && (musicItems.length > 0 || musicsLoading)) || selected === 'Musiques'
|
||||
|
||||
const shouldShowPlaybacks =
|
||||
(!selected && (playbacks.length > 0 || playbacksLoading)) ||
|
||||
selected === "Playback";
|
||||
(!selected && (playbacks.length > 0 || playbacksLoading)) || selected === 'Playback'
|
||||
|
||||
const shouldShowUsers =
|
||||
(!selected && (users.length > 0 || usersLoading)) || selected === "Profils";
|
||||
(!selected && (users.length > 0 || usersLoading)) || selected === 'Profils'
|
||||
|
||||
return (
|
||||
<View style={[{ flex: 1 }, style]}>
|
||||
@@ -154,7 +138,7 @@ const SearchResultsList = ({
|
||||
musicItems.slice(0, 6).map((project) => (
|
||||
<MusicCard
|
||||
key={project.id}
|
||||
title={project?.title || "Sans titre"}
|
||||
title={project?.title || 'Sans titre'}
|
||||
subtitle={project?.userName}
|
||||
imageUri={resolveCoverUri(project)}
|
||||
projectId={project?.id}
|
||||
@@ -162,13 +146,12 @@ const SearchResultsList = ({
|
||||
likeTarget={LIKE_TARGET.SONG}
|
||||
onPress={() => handleMusicPress(project)}
|
||||
onPressMore={(positionTop) => {
|
||||
setSelectedProjectId(project.id);
|
||||
setMenuPosition(positionTop);
|
||||
setSelectedProjectId(project.id)
|
||||
setMenuPosition(positionTop)
|
||||
setShowMenu(
|
||||
(previous) =>
|
||||
!previous ||
|
||||
positionTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
!previous || positionTop?.top !== (menuPosition?.top ?? null)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -178,16 +161,16 @@ const SearchResultsList = ({
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
alignSelf: "center",
|
||||
alignSelf: 'center',
|
||||
}}
|
||||
>
|
||||
{"Chargement…"}
|
||||
{'Chargement…'}
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{musicItems.length === 0 && !musicsLoading && (
|
||||
<EmptyText text={"Aucune musique trouvée"} />
|
||||
<EmptyText text={'Aucune musique trouvée'} />
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
@@ -199,7 +182,7 @@ const SearchResultsList = ({
|
||||
playbacks.slice(0, 6).map((project) => (
|
||||
<MusicCard
|
||||
key={project.id}
|
||||
title={project?.title || "Sans titre"}
|
||||
title={project?.title || 'Sans titre'}
|
||||
subtitle={project?.userName}
|
||||
imageUri={resolveCoverUri(project, {
|
||||
preferThumbnail: true,
|
||||
@@ -209,13 +192,12 @@ const SearchResultsList = ({
|
||||
likeTarget={LIKE_TARGET.PLAYBACK}
|
||||
onPress={() => handlePlaybackPress(project)}
|
||||
onPressMore={(positionTop) => {
|
||||
setSelectedProjectId(project.id);
|
||||
setMenuPosition(positionTop);
|
||||
setSelectedProjectId(project.id)
|
||||
setMenuPosition(positionTop)
|
||||
setShowMenu(
|
||||
(previous) =>
|
||||
!previous ||
|
||||
positionTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
!previous || positionTop?.top !== (menuPosition?.top ?? null)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -225,24 +207,22 @@ const SearchResultsList = ({
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
alignSelf: "center",
|
||||
alignSelf: 'center',
|
||||
}}
|
||||
>
|
||||
{"Chargement…"}
|
||||
{'Chargement…'}
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{playbacks.length === 0 && !playbacksLoading && (
|
||||
<EmptyText text={"Aucun playback trouvé"} />
|
||||
<EmptyText text={'Aucun playback trouvé'} />
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{shouldShowUsers && (
|
||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||
<CreateLyricsHeader
|
||||
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
||||
>
|
||||
<CreateLyricsHeader gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}>
|
||||
{users.length > 0 && (
|
||||
<View style={{ gap: 8 }}>
|
||||
{Array.isArray(users) &&
|
||||
@@ -255,7 +235,7 @@ const SearchResultsList = ({
|
||||
<ProfilePicture
|
||||
uri={user?.profilePictureURL || defaultAvatar}
|
||||
size={60}
|
||||
imageProps={{ priority: "high" }}
|
||||
imageProps={{ priority: 'high' }}
|
||||
/>
|
||||
<Text
|
||||
style={{
|
||||
@@ -264,7 +244,7 @@ const SearchResultsList = ({
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
{getArtistDisplayName(user, "Utilisateur")}
|
||||
{getArtistDisplayName(user, 'Utilisateur')}
|
||||
</Text>
|
||||
</Pressable>
|
||||
))}
|
||||
@@ -274,26 +254,22 @@ const SearchResultsList = ({
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
alignSelf: "center",
|
||||
alignSelf: 'center',
|
||||
}}
|
||||
>
|
||||
{"Chargement…"}
|
||||
{'Chargement…'}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{users.length === 0 && !usersLoading && (
|
||||
<EmptyText text={"Aucun profil trouvé"} />
|
||||
)}
|
||||
{users.length === 0 && !usersLoading && <EmptyText text={'Aucun profil trouvé'} />}
|
||||
</CreateLyricsHeader>
|
||||
</View>
|
||||
)}
|
||||
{selected === "Clips" && (
|
||||
{selected === 'Clips' && (
|
||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||
<CreateLyricsHeader
|
||||
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
||||
>
|
||||
<EmptyText text={"Aucun clip trouvé"} />
|
||||
<CreateLyricsHeader gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}>
|
||||
<EmptyText text={'Aucun clip trouvé'} />
|
||||
</CreateLyricsHeader>
|
||||
</View>
|
||||
)}
|
||||
@@ -307,7 +283,7 @@ const SearchResultsList = ({
|
||||
projectId={selectedProjectId}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchResultsList;
|
||||
export default SearchResultsList
|
||||
|
||||
Reference in New Issue
Block a user