last tickets
This commit is contained in:
@@ -56,6 +56,8 @@ const AppActionSheet = ({
|
||||
width: 50,
|
||||
zIndex: 2,
|
||||
}}
|
||||
closeOnTouchBackdrop
|
||||
closeOnPressBack
|
||||
onClose={onClose}
|
||||
{...sheetProps}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import React from "react";
|
||||
import { StyleSheet, Text, View } from "react-native";
|
||||
import { gutters, Palette } from "../styles";
|
||||
import { FONT_FAMILY } from "../styles/Fonts";
|
||||
import BorderGradientButton from "./BorderGradientButton";
|
||||
import GradientButton from "./GradientButton";
|
||||
import Overlay from "./Overlay";
|
||||
|
||||
const SubscriptionConfirmModal = ({
|
||||
isVisible,
|
||||
setIsVisible,
|
||||
onJoinClub,
|
||||
onContinue,
|
||||
continueLabel = "Continuer vers la création de playback",
|
||||
}) => {
|
||||
const handleJoinClub = () => {
|
||||
if (typeof setIsVisible === "function") {
|
||||
setIsVisible(false);
|
||||
}
|
||||
if (typeof onJoinClub === "function") {
|
||||
onJoinClub();
|
||||
}
|
||||
};
|
||||
|
||||
const handleContinue = () => {
|
||||
if (typeof setIsVisible === "function") {
|
||||
setIsVisible(false);
|
||||
}
|
||||
if (typeof onContinue === "function") {
|
||||
onContinue();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Overlay
|
||||
isVisible={isVisible}
|
||||
setIsVisible={setIsVisible}
|
||||
blurIntensity={15}
|
||||
>
|
||||
<View style={styles.modalCard}>
|
||||
<Text style={styles.modalTitle}>
|
||||
Continuer sans générer de revenus ?
|
||||
</Text>
|
||||
<Text style={styles.modalDescription}>
|
||||
Rejoins le Club Musicland pour monétiser tes écoutes et accéder aux
|
||||
concours.
|
||||
</Text>
|
||||
<View style={styles.modalActions}>
|
||||
<GradientButton
|
||||
title="Rejoindre le club"
|
||||
onPress={handleJoinClub}
|
||||
containerStyle={styles.modalAction}
|
||||
/>
|
||||
<BorderGradientButton
|
||||
title={continueLabel}
|
||||
onPress={handleContinue}
|
||||
containerStyle={styles.modalAction}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Overlay>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubscriptionConfirmModal;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalCard: {
|
||||
width: "90%",
|
||||
maxWidth: 420,
|
||||
alignSelf: "center",
|
||||
padding: gutters * 1.4,
|
||||
borderRadius: 20,
|
||||
backgroundColor: "rgba(37, 36, 56, 0.96)",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255, 255, 255, 0.12)",
|
||||
gap: gutters * 0.8,
|
||||
},
|
||||
modalTitle: {
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
fontSize: 18,
|
||||
color: Palette.white,
|
||||
textAlign: "center",
|
||||
},
|
||||
modalDescription: {
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
fontSize: 14,
|
||||
lineHeight: 20,
|
||||
color: Palette.grayMid,
|
||||
textAlign: "center",
|
||||
},
|
||||
modalActions: {
|
||||
gap: gutters * 0.6,
|
||||
marginTop: gutters * 0.6,
|
||||
},
|
||||
modalAction: {
|
||||
width: "100%",
|
||||
},
|
||||
});
|
||||
@@ -1,4 +1,10 @@
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import {
|
||||
Image,
|
||||
Pressable,
|
||||
@@ -6,6 +12,7 @@ import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
findNodeHandle,
|
||||
} from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import AppActionSheet from "../AppActionSheet";
|
||||
@@ -25,6 +32,7 @@ const PlaybackPickerModal = () => {
|
||||
const { userProjects = [], createNewProject } = useUserData();
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [webVisible, setWebVisible] = useState(true);
|
||||
const modalRef = useRef(null);
|
||||
|
||||
const sanitizedProjects = useMemo(() => {
|
||||
if (!Array.isArray(userProjects)) {
|
||||
@@ -101,13 +109,45 @@ const PlaybackPickerModal = () => {
|
||||
|
||||
const hasProjects = sanitizedProjects.length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isWeb || !webVisible || typeof document === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const handlePointerDown = (event) => {
|
||||
const node = modalRef.current;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
const domNode = findNodeHandle(node);
|
||||
if (domNode && typeof domNode.contains === "function") {
|
||||
if (domNode.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (domNode === event.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
hideSheet();
|
||||
};
|
||||
|
||||
document.addEventListener("pointerdown", handlePointerDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("pointerdown", handlePointerDown);
|
||||
};
|
||||
}, [hideSheet, webVisible]);
|
||||
|
||||
if (isWeb && !webVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AppActionSheet id={SHEET_ID} webModal onClose={hideSheet}>
|
||||
<View style={{ gap: 18 }}>
|
||||
<View ref={modalRef} style={{ gap: 18 }} collapsable={false}>
|
||||
<Text style={styles.title}>Ajouter un playback</Text>
|
||||
<Text style={styles.description}>
|
||||
Choisis une musique déjà créée pour y ajouter un playback ou lance un
|
||||
|
||||
@@ -6,7 +6,16 @@ import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import BorderGradientButton from "../BorderGradientButton";
|
||||
import GradientButton from "../GradientButton";
|
||||
|
||||
const ValidateModal = ({ visible, onClose, onPressValidate }) => {
|
||||
const ValidateModal = ({
|
||||
visible,
|
||||
onClose,
|
||||
onPressValidate,
|
||||
onPressSecondary,
|
||||
title = "Attention !",
|
||||
description = "Lorsque tu clique sur valider, tu ne pourra plus changer ni le texte ni la mélodie.",
|
||||
primaryLabel = "Valider",
|
||||
secondaryLabel = "Retour",
|
||||
}) => {
|
||||
return (
|
||||
<Modal
|
||||
animationType="slide"
|
||||
@@ -36,7 +45,7 @@ const ValidateModal = ({ visible, onClose, onPressValidate }) => {
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
Attention !
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
@@ -46,17 +55,22 @@ const ValidateModal = ({ visible, onClose, onPressValidate }) => {
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
Lorsque tu clique sur valider, tu ne pourra plus changer ni le
|
||||
texte ni la mélodie.
|
||||
{description}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ width: "85%", alignSelf: "center", gap: 15 }}>
|
||||
<BorderGradientButton title="Retour" onPress={onClose} />
|
||||
<GradientButton
|
||||
title="Valider"
|
||||
<BorderGradientButton
|
||||
title={secondaryLabel}
|
||||
onPress={() => {
|
||||
onClose();
|
||||
onClose?.();
|
||||
onPressSecondary?.();
|
||||
}}
|
||||
/>
|
||||
<GradientButton
|
||||
title={primaryLabel}
|
||||
onPress={() => {
|
||||
onClose?.();
|
||||
onPressValidate?.();
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Image, Pressable, StyleSheet, Text, View } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
import { icons, img } from "../../assets";
|
||||
import { arrayRemove, arrayUnion, projectsRef } from "../../config/firebase";
|
||||
import { projectsRef } from "../../config/firebase";
|
||||
import useDataFromRef from "../../hooks/useDataFromRef";
|
||||
import { isWeb } from "../../hooks/useLayoutType";
|
||||
import usePlayer from "../../hooks/usePlayer";
|
||||
@@ -13,6 +13,11 @@ import { useUser } from "../../providers/UserDataProvider";
|
||||
import { gutters, Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { ensureAuthenticated } from "../../utils/authRedirect";
|
||||
import {
|
||||
getProjectLikes,
|
||||
LIKE_TARGET,
|
||||
toggleProjectLike,
|
||||
} from "../../utils/likes";
|
||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||
|
||||
const formatDuration = (ms) => {
|
||||
@@ -60,9 +65,9 @@ const GlobalAudioPlayer = () => {
|
||||
refreshArray: [projectId],
|
||||
});
|
||||
|
||||
const likedByList = Array.isArray(projectData?.likedBy)
|
||||
? projectData.likedBy
|
||||
: [];
|
||||
const likedByList = useMemo(() => {
|
||||
return getProjectLikes(projectData, LIKE_TARGET.SONG);
|
||||
}, [projectData]);
|
||||
|
||||
const likedFromDoc = useMemo(() => {
|
||||
if (!projectId || !currentUID) return false;
|
||||
@@ -100,12 +105,12 @@ const GlobalAudioPlayer = () => {
|
||||
const next = !effectiveIsLiked;
|
||||
setPendingLike(next);
|
||||
try {
|
||||
await projectsRef.doc(projectId).set(
|
||||
{
|
||||
likedBy: next ? arrayUnion(currentUID) : arrayRemove(currentUID),
|
||||
},
|
||||
{ merge: true },
|
||||
);
|
||||
await toggleProjectLike({
|
||||
projectId,
|
||||
target: LIKE_TARGET.SONG,
|
||||
currentUID,
|
||||
next,
|
||||
});
|
||||
} catch (_error) {
|
||||
setPendingLike(null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user