buid and fix bottom sheet and react native compressor
This commit is contained in:
@@ -49,7 +49,10 @@ const AppActionSheet = ({
|
||||
return (
|
||||
<ActionSheet
|
||||
id={id}
|
||||
containerStyle={{ backgroundColor: Palette.tran }}
|
||||
containerStyle={[
|
||||
{ backgroundColor: Palette.tran },
|
||||
isWeb && { alignItems: "center" },
|
||||
]}
|
||||
gestureEnabled
|
||||
indicatorStyle={{
|
||||
top: 20,
|
||||
@@ -61,18 +64,18 @@ const AppActionSheet = ({
|
||||
>
|
||||
<BlurView
|
||||
intensity={Platform.OS === "ios" || isWeb ? 20 : 10}
|
||||
style={{
|
||||
paddingTop: 36,
|
||||
paddingHorizontal: 14,
|
||||
paddingBottom: gutters + (insets?.bottom || 0),
|
||||
backgroundColor: Palette.glass,
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
// experimentalBlurMethod={
|
||||
// Platform.OS !== "ios" ? "dimezisBlurView" : "none"
|
||||
// }
|
||||
style={[
|
||||
{
|
||||
paddingTop: 36,
|
||||
paddingHorizontal: 14,
|
||||
paddingBottom: gutters + (insets?.bottom || 0),
|
||||
backgroundColor: Palette.glass,
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
overflow: "hidden",
|
||||
},
|
||||
isWeb && { width: 700 },
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</BlurView>
|
||||
@@ -99,8 +102,7 @@ const styles = StyleSheet.create({
|
||||
padding: 24,
|
||||
},
|
||||
webModalCard: {
|
||||
width: 480,
|
||||
maxWidth: "90%",
|
||||
maxWidth: 500,
|
||||
borderRadius: 28,
|
||||
overflow: "hidden",
|
||||
backgroundColor: Palette.glass,
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import React, { useCallback } from "react";
|
||||
import { Pressable, Text, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import AppActionSheet from "../AppActionSheet";
|
||||
|
||||
const OptionButton = ({ label, onPress, disabled = false }) => (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
style={({ pressed }) => ({
|
||||
paddingVertical: 14,
|
||||
paddingHorizontal: 18,
|
||||
borderRadius: 16,
|
||||
backgroundColor: "rgba(255,255,255,0.08)",
|
||||
opacity: disabled ? 0.5 : 1,
|
||||
transform: [{ scale: pressed ? 0.97 : 1 }],
|
||||
})}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
const MusicOptionsModal = ({ payload }) => {
|
||||
const {
|
||||
onReport,
|
||||
onAddToPlaylist,
|
||||
onDownload,
|
||||
downloadDisabled = false,
|
||||
projectId = null,
|
||||
ownerId = null,
|
||||
title = null,
|
||||
} = payload || {};
|
||||
|
||||
const trigger = useCallback((action) => {
|
||||
Promise.resolve(SheetManager.hide("MusicOptions"))
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
if (typeof action === "function") {
|
||||
setTimeout(action, 220);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleReport = useCallback(() => {
|
||||
const run = () => {
|
||||
if (typeof onReport === "function") {
|
||||
onReport();
|
||||
return;
|
||||
}
|
||||
if (projectId) {
|
||||
SheetManager.show("Report", {
|
||||
payload: {
|
||||
targetType: "music",
|
||||
projectId,
|
||||
title,
|
||||
ownerId,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
trigger(run);
|
||||
}, [onReport, ownerId, projectId, title, trigger]);
|
||||
|
||||
const handleAddToPlaylist = useCallback(() => {
|
||||
const run = () => {
|
||||
if (typeof onAddToPlaylist === "function") {
|
||||
onAddToPlaylist();
|
||||
return;
|
||||
}
|
||||
if (projectId) {
|
||||
SheetManager.show("Playlist", { payload: { projectId } });
|
||||
} else {
|
||||
SheetManager.show("Playlist");
|
||||
}
|
||||
};
|
||||
trigger(run);
|
||||
}, [onAddToPlaylist, projectId, trigger]);
|
||||
|
||||
const handleDownload = useCallback(() => {
|
||||
if (downloadDisabled) return;
|
||||
const run = () => {
|
||||
if (typeof onDownload === "function") {
|
||||
onDownload();
|
||||
}
|
||||
};
|
||||
trigger(run);
|
||||
}, [downloadDisabled, onDownload, trigger]);
|
||||
|
||||
return (
|
||||
<AppActionSheet id="MusicOptions">
|
||||
<View style={{ gap: 20 }}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.HelveticaNeueMedium,
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
Options
|
||||
</Text>
|
||||
<View style={{ gap: 12 }}>
|
||||
<OptionButton label="Signaler" onPress={handleReport} />
|
||||
<OptionButton
|
||||
label="Ajouter à une playlist"
|
||||
onPress={handleAddToPlaylist}
|
||||
/>
|
||||
<OptionButton
|
||||
label="Télécharger"
|
||||
onPress={handleDownload}
|
||||
disabled={downloadDisabled}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</AppActionSheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default MusicOptionsModal;
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
Linking,
|
||||
} from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import {
|
||||
@@ -17,7 +18,6 @@ import {
|
||||
import { useGlobal } from "reactn";
|
||||
import { background, icons } from "../../assets";
|
||||
import PressableScale from "../../components/PressableScale";
|
||||
import ShareBtn from "../../components/ShareBtn/ShareBtn";
|
||||
import Slider from "../../components/Slider";
|
||||
import {
|
||||
arrayRemove,
|
||||
@@ -38,11 +38,6 @@ import {
|
||||
getSegmentMeta,
|
||||
normalizeStructureType,
|
||||
} from "../../utils/songStructure";
|
||||
import {
|
||||
createMusicSharePayload,
|
||||
openShareSheet,
|
||||
} from "../../utils/shareSheet";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
|
||||
// 20 secondes
|
||||
const timeBeforeIncrement = 20000;
|
||||
@@ -113,21 +108,6 @@ const MusicDetails = ({ route }) => {
|
||||
};
|
||||
}, [trackId, songUrl, title, artist, coverUrl, projectId]);
|
||||
|
||||
const sharePayload = useMemo(
|
||||
() =>
|
||||
createMusicSharePayload({
|
||||
projectId,
|
||||
title,
|
||||
artist,
|
||||
}),
|
||||
[projectId, title, artist]
|
||||
);
|
||||
|
||||
const handleShare = useCallback(() => {
|
||||
if (!sharePayload) return;
|
||||
openShareSheet(sharePayload);
|
||||
}, [sharePayload]);
|
||||
|
||||
const handleReport = useCallback(() => {
|
||||
if (!projectId) return;
|
||||
SheetManager.show("Report", {
|
||||
@@ -140,6 +120,46 @@ const MusicDetails = ({ route }) => {
|
||||
});
|
||||
}, [owner?.id, project?.userId, projectId, title]);
|
||||
|
||||
const handleAddToPlaylist = useCallback(() => {
|
||||
if (projectId) {
|
||||
SheetManager.show("Playlist", { payload: { projectId } });
|
||||
} else {
|
||||
SheetManager.show("Playlist");
|
||||
}
|
||||
}, [projectId]);
|
||||
|
||||
const handleDownload = useCallback(async () => {
|
||||
if (!songUrl) return;
|
||||
try {
|
||||
await Linking.openURL(songUrl);
|
||||
} catch (error) {
|
||||
console.log("MusicDetails download error", error?.message);
|
||||
}
|
||||
}, [songUrl]);
|
||||
|
||||
const handleOpenOptions = useCallback(() => {
|
||||
SheetManager.show("MusicOptions", {
|
||||
payload: {
|
||||
projectId,
|
||||
title,
|
||||
ownerId: project?.userId || owner?.id || null,
|
||||
onReport: handleReport,
|
||||
onAddToPlaylist: handleAddToPlaylist,
|
||||
onDownload: handleDownload,
|
||||
downloadDisabled: !songUrl,
|
||||
},
|
||||
});
|
||||
}, [
|
||||
handleAddToPlaylist,
|
||||
handleDownload,
|
||||
handleReport,
|
||||
owner?.id,
|
||||
project?.userId,
|
||||
projectId,
|
||||
songUrl,
|
||||
title,
|
||||
]);
|
||||
|
||||
const {
|
||||
isCurrent: isCurrentTrack,
|
||||
isPlaying: isTrackPlaying,
|
||||
@@ -709,40 +729,30 @@ const MusicDetails = ({ route }) => {
|
||||
if (!projectId || !currentUID) return;
|
||||
const next = !fav;
|
||||
setFav(next);
|
||||
try {
|
||||
await projectsRef.doc(projectId).update({
|
||||
likedBy: next
|
||||
? arrayUnion(currentUID)
|
||||
: arrayRemove(currentUID),
|
||||
});
|
||||
} catch (e) {
|
||||
setFav(!next);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<RNImage
|
||||
source={fav ? icons.heart : icons.heartOutline}
|
||||
style={{ ...size({ size: 24 }) }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</PressableScale>
|
||||
<PressableScale onPress={handleReport}>
|
||||
<Feather name="flag" size={22} color={Palette.white} style={{ marginHorizontal: 2 }} />
|
||||
</PressableScale>
|
||||
{!!sharePayload && (
|
||||
<ShareBtn style={{ borderRadius: 18 }} onPress={handleShare} />
|
||||
)}
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
SheetManager.show("Playlist", { payload: { projectId } })
|
||||
}
|
||||
>
|
||||
<RNImage
|
||||
source={icons.more}
|
||||
style={{ ...size({ size: 24 }) }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
try {
|
||||
await projectsRef.doc(projectId).update({
|
||||
likedBy: next
|
||||
? arrayUnion(currentUID)
|
||||
: arrayRemove(currentUID),
|
||||
});
|
||||
} catch (e) {
|
||||
setFav(!next);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<RNImage
|
||||
source={fav ? icons.heart : icons.heartOutline}
|
||||
style={{ ...size({ size: 24 }) }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</PressableScale>
|
||||
<PressableScale onPress={handleOpenOptions}>
|
||||
<RNImage
|
||||
source={icons.more}
|
||||
style={{ ...size({ size: 24 }) }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</PressableScale>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -24,7 +24,6 @@ import { useGlobal } from "reactn";
|
||||
import { background, icons } from "../../assets";
|
||||
import PressableScale from "../../components/PressableScale";
|
||||
import Slider from "../../components/Slider";
|
||||
import Svg, { Circle } from "react-native-svg";
|
||||
import {
|
||||
arrayRemove,
|
||||
arrayUnion,
|
||||
@@ -50,7 +49,6 @@ import {
|
||||
createMusicSharePayload,
|
||||
openShareSheet,
|
||||
} from "../../utils/shareSheet";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
|
||||
// 20 secondes
|
||||
const timeBeforeIncrement = 20000;
|
||||
@@ -227,6 +225,38 @@ const MusicDetails = ({ route }) => {
|
||||
});
|
||||
}, [owner?.id, project?.userId, projectId, title]);
|
||||
|
||||
const handleAddToPlaylist = useCallback(() => {
|
||||
if (projectId) {
|
||||
SheetManager.show("Playlist", { payload: { projectId } });
|
||||
} else {
|
||||
SheetManager.show("Playlist");
|
||||
}
|
||||
}, [projectId]);
|
||||
|
||||
const handleOpenOptions = useCallback(() => {
|
||||
SheetManager.show("MusicOptions", {
|
||||
payload: {
|
||||
projectId,
|
||||
title,
|
||||
ownerId: project?.userId || owner?.id || null,
|
||||
onReport: handleReport,
|
||||
onAddToPlaylist: handleAddToPlaylist,
|
||||
onDownload: handleDownload,
|
||||
downloadDisabled: isDownloading || !songUrl,
|
||||
},
|
||||
});
|
||||
}, [
|
||||
handleAddToPlaylist,
|
||||
handleDownload,
|
||||
handleReport,
|
||||
isDownloading,
|
||||
owner?.id,
|
||||
project?.userId,
|
||||
projectId,
|
||||
songUrl,
|
||||
title,
|
||||
]);
|
||||
|
||||
const {
|
||||
isCurrent: isCurrentTrack,
|
||||
isPlaying: isTrackPlaying,
|
||||
@@ -913,56 +943,13 @@ const MusicDetails = ({ route }) => {
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
<PressableScale onPress={handleReport}>
|
||||
<Feather
|
||||
name="flag"
|
||||
size={22}
|
||||
color={Palette.white}
|
||||
style={{ marginHorizontal: 2 }}
|
||||
/>
|
||||
</PressableScale>
|
||||
<View
|
||||
style={{
|
||||
width: 36,
|
||||
height: 36,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{isDownloading ? (
|
||||
<DownloadProgressRing
|
||||
progress={downloadProgress}
|
||||
size={36}
|
||||
strokeWidth={3}
|
||||
/>
|
||||
) : null}
|
||||
<Pressable
|
||||
onPress={handleDownload}
|
||||
disabled={isDownloading || !songUrl}
|
||||
style={{
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 18,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "rgba(255,255,255,0.08)",
|
||||
opacity: isDownloading || !songUrl ? 0.6 : 1,
|
||||
}}
|
||||
>
|
||||
<Feather name="download" size={18} color={Palette.white} />
|
||||
</Pressable>
|
||||
</View>
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
SheetManager.show("Playlist", { payload: { projectId } })
|
||||
}
|
||||
>
|
||||
<PressableScale onPress={handleOpenOptions}>
|
||||
<RNImage
|
||||
source={icons.more}
|
||||
style={{ ...size({ size: 24 }) }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
</PressableScale>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -1166,38 +1153,3 @@ const styles = StyleSheet.create({
|
||||
marginBottom: 6,
|
||||
},
|
||||
});
|
||||
|
||||
const DownloadProgressRing = ({ progress = 0, size = 36, strokeWidth = 3 }) => {
|
||||
const radius = size / 2 - strokeWidth / 2;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
const clamped = Math.max(0, Math.min(1, progress || 0));
|
||||
const offset = circumference * (1 - clamped);
|
||||
|
||||
return (
|
||||
<Svg
|
||||
width={size}
|
||||
height={size}
|
||||
style={{ position: "absolute", top: 0, left: 0 }}
|
||||
>
|
||||
<Circle
|
||||
cx={size / 2}
|
||||
cy={size / 2}
|
||||
r={radius}
|
||||
stroke="rgba(255, 255, 255, 0.15)"
|
||||
strokeWidth={strokeWidth}
|
||||
fill="transparent"
|
||||
/>
|
||||
<Circle
|
||||
cx={size / 2}
|
||||
cy={size / 2}
|
||||
r={radius}
|
||||
stroke={Palette.primary}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeDasharray={`${circumference} ${circumference}`}
|
||||
strokeDashoffset={offset}
|
||||
strokeLinecap="round"
|
||||
fill="transparent"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ import PlaylistModal from "../components/modal/PlaylistModal";
|
||||
import PlaybackPickerModal from "../components/modal/PlaybackPickerModal";
|
||||
import ShareModal from "../components/modal/ShareModal";
|
||||
import ReportModal from "../components/modal/ReportModal";
|
||||
import MusicOptionsModal from "../components/modal/MusicOptionsModal";
|
||||
|
||||
registerSheet("Delete", DeleteModal);
|
||||
registerSheet("ProfileSettings", ProfileSettingsModal);
|
||||
@@ -18,5 +19,6 @@ registerSheet("Playlist", PlaylistModal);
|
||||
registerSheet("PlaybackPicker", PlaybackPickerModal);
|
||||
registerSheet("Share", ShareModal);
|
||||
registerSheet("Report", ReportModal);
|
||||
registerSheet("MusicOptions", MusicOptionsModal);
|
||||
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user