297 lines
9.2 KiB
JavaScript
297 lines
9.2 KiB
JavaScript
import { useRoute } from '@react-navigation/native'
|
|
import React, { useCallback, useMemo, useState } from 'react'
|
|
import { Linking, StyleSheet, Text, View } from 'react-native'
|
|
import useMinuit from 'react-native-minuit/src/hooks/useMinuit.js'
|
|
import { background } from '../../assets'
|
|
import AppCheckbox from '../../components/AppCheckbox'
|
|
import BorderGradientButton from '../../components/BorderGradientButton'
|
|
import GradientButton from '../../components/GradientButton'
|
|
import MusicLandHeader from '../../components/MusicLandHeader'
|
|
import alert from '../../components/Alert'
|
|
import firebase, { projectsRef, serverTimestamp } from '../../config/firebase'
|
|
import Page from '../../layouts/Page'
|
|
import { goBack } from '../../navigation/NavigationService'
|
|
import { useUser } from '../../providers/UserDataProvider'
|
|
import { Palette, gutters } from '../../styles'
|
|
import { FONT_FAMILY } from '../../styles/Fonts'
|
|
|
|
const PublishYoutube = () => {
|
|
const route = useRoute()
|
|
const routeProjectId = route?.params?.projectId ?? null
|
|
const { userProjects = [], selectedProject } = useUser()
|
|
const { setTooltip } = useMinuit()
|
|
|
|
const project = useMemo(() => {
|
|
if (routeProjectId) {
|
|
return userProjects.find((item) => item?.id === routeProjectId) || selectedProject || null
|
|
}
|
|
if (selectedProject?.id) {
|
|
return selectedProject
|
|
}
|
|
return userProjects.length ? userProjects[0] : null
|
|
}, [routeProjectId, selectedProject, userProjects])
|
|
|
|
const projectId = project?.id || routeProjectId || null
|
|
|
|
const [saving, setSaving] = useState(false)
|
|
const [hasAcceptedPublication, setHasAcceptedPublication] = useState(true)
|
|
const youtubeUrl = project?.youtubeUrl ?? null
|
|
const youtubeStatus = project?.youtubeStatus ?? null
|
|
const youtubeError = project?.youtubeError ?? null
|
|
const playbackReady = !!project?.playbackUrl
|
|
const hasYoutubePublication = !!youtubeUrl
|
|
const isPublishing = useMemo(
|
|
() => ['PUBLISHING', 'UPLOADING', 'PROCESSING', 'QUEUED'].includes(youtubeStatus),
|
|
[youtubeStatus]
|
|
)
|
|
const publishDisabled =
|
|
saving || isPublishing || !playbackReady || !projectId || !hasAcceptedPublication
|
|
const publishButtonLabel = isPublishing
|
|
? 'Publication en cours...'
|
|
: hasYoutubePublication
|
|
? 'Mettre à jour sur YouTube'
|
|
: 'Publier sur YouTube'
|
|
const statusMessage = useMemo(() => {
|
|
if (!playbackReady) {
|
|
return 'Termine la création de ton playback avec Theo pour débloquer la publication YouTube.'
|
|
}
|
|
if (isPublishing) {
|
|
return 'La publication de ta vidéo est en cours... Patiente un instant.'
|
|
}
|
|
if (youtubeError || youtubeStatus === 'FAILED') {
|
|
return 'La dernière tentative de publication a échoué. Tu peux réessayer ci-dessous.'
|
|
}
|
|
if (hasYoutubePublication) {
|
|
return 'Ta vidéo est publiée sur la chaîne YouTube MusicLand. Tu peux la partager dès maintenant.'
|
|
}
|
|
return 'Partage ton playback sur la chaîne YouTube MusicLand.'
|
|
}, [hasYoutubePublication, isPublishing, playbackReady, youtubeError, youtubeStatus])
|
|
|
|
const handleOpenYoutube = useCallback(async () => {
|
|
if (!youtubeUrl) {
|
|
return
|
|
}
|
|
try {
|
|
await Linking.openURL(youtubeUrl)
|
|
} catch (_error) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: "Impossible d'ouvrir le lien YouTube",
|
|
})
|
|
}
|
|
}, [setTooltip, youtubeUrl])
|
|
|
|
const handleMarkPublished = useCallback(async () => {
|
|
if (!projectId) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: 'Sélectionnez un projet avant de publier',
|
|
})
|
|
return
|
|
}
|
|
if (!playbackReady) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: "Aucun playback n'est disponible pour la publication",
|
|
})
|
|
return
|
|
}
|
|
setSaving(true)
|
|
try {
|
|
// publication sur youtube en standby
|
|
// const publishCallable = firebase.functions().httpsCallable('youtube-publishPlaybackToYoutube')
|
|
// await publishCallable({ projectId })
|
|
setTooltip?.({
|
|
type: 'success',
|
|
text: 'Publication lancée sur YouTube',
|
|
})
|
|
} catch (error) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: error?.message || 'Impossible de lancer la publication',
|
|
})
|
|
} finally {
|
|
setSaving(false)
|
|
}
|
|
}, [playbackReady, projectId, setTooltip])
|
|
|
|
const handleConfirmPublish = useCallback(() => {
|
|
if (!hasAcceptedPublication) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: 'Confirme la diffusion sur YouTube avant de publier',
|
|
})
|
|
return
|
|
}
|
|
if (publishDisabled) {
|
|
return
|
|
}
|
|
const confirmTitle = hasYoutubePublication
|
|
? 'Confirmer la mise à jour'
|
|
: 'Confirmer la publication'
|
|
const confirmDescription = hasYoutubePublication
|
|
? 'La vidéo existe déjà sur YouTube. Confirme que tu souhaites remplacer la version publiée.'
|
|
: 'Confirme que tu souhaites publier ce playback sur YouTube. Il sera visible publiquement.'
|
|
alert(confirmTitle, confirmDescription, [
|
|
{ text: 'Annuler', style: 'cancel' },
|
|
{
|
|
text: hasYoutubePublication ? 'Mettre à jour' : 'Je confirme',
|
|
onPress: handleMarkPublished,
|
|
},
|
|
])
|
|
}, [
|
|
handleMarkPublished,
|
|
hasAcceptedPublication,
|
|
hasYoutubePublication,
|
|
publishDisabled,
|
|
setTooltip,
|
|
])
|
|
|
|
const handleResetPublication = useCallback(async () => {
|
|
if (!projectId) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: 'Sélectionnez un projet avant de réinitialiser',
|
|
})
|
|
return
|
|
}
|
|
setSaving(true)
|
|
try {
|
|
await projectsRef.doc(projectId).set(
|
|
{
|
|
youtubePublished: false,
|
|
youtubeUrl: null,
|
|
youtubeVideoId: null,
|
|
youtubePublishedAt: null,
|
|
youtubeStatus: 'IDLE',
|
|
youtubeError: null,
|
|
updatedAt: serverTimestamp(),
|
|
},
|
|
{ merge: true }
|
|
)
|
|
setTooltip?.({
|
|
type: 'success',
|
|
text: 'Publication YouTube réinitialisée',
|
|
})
|
|
} catch (error) {
|
|
setTooltip?.({
|
|
type: 'error',
|
|
text: error?.message || 'Réinitialisation impossible',
|
|
})
|
|
} finally {
|
|
setSaving(false)
|
|
}
|
|
}, [projectId, setTooltip])
|
|
|
|
return (
|
|
<Page backgroundImg={background.playbackBG2} headerType="NONE">
|
|
<MusicLandHeader progress={100} onPressBack={goBack} />
|
|
<View
|
|
style={{
|
|
flex: 1,
|
|
paddingHorizontal: gutters,
|
|
paddingBottom: gutters * 2,
|
|
justifyContent: 'space-between',
|
|
}}
|
|
>
|
|
<View style={{ alignItems: 'center', gap: 18 }}>
|
|
<Text
|
|
style={{
|
|
fontSize: 22,
|
|
fontFamily: FONT_FAMILY.InterSemiBold,
|
|
color: Palette.white,
|
|
textAlign: 'center',
|
|
}}
|
|
>
|
|
{hasYoutubePublication ? 'Ta vidéo est déjà sur YouTube' : 'Publier sur YouTube'}
|
|
</Text>
|
|
<Text
|
|
style={{
|
|
fontSize: 14,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
color: Palette.white,
|
|
opacity: 0.9,
|
|
textAlign: 'center',
|
|
lineHeight: 20,
|
|
}}
|
|
>
|
|
{statusMessage}
|
|
</Text>
|
|
{youtubeError && (
|
|
<Text
|
|
style={{
|
|
fontSize: 13,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
color: Palette.red,
|
|
textAlign: 'center',
|
|
}}
|
|
>
|
|
{youtubeError}
|
|
</Text>
|
|
)}
|
|
{hasYoutubePublication && youtubeUrl && (
|
|
<Text
|
|
style={{
|
|
fontSize: 13,
|
|
fontFamily: FONT_FAMILY.InterMedium,
|
|
color: Palette.white,
|
|
textAlign: 'center',
|
|
opacity: 0.8,
|
|
}}
|
|
numberOfLines={2}
|
|
>
|
|
{youtubeUrl}
|
|
</Text>
|
|
)}
|
|
</View>
|
|
<View style={{ gap: 14 }}>
|
|
<View style={styles.consentContainer}>
|
|
<AppCheckbox
|
|
selected={hasAcceptedPublication}
|
|
onPress={() => setHasAcceptedPublication((prevState) => !prevState)}
|
|
label="J'accepte la diffusion de mon contenu sur YouTube."
|
|
/>
|
|
<Text style={styles.consentDescription}>
|
|
Cette confirmation est requise avant toute publication sur YouTube.
|
|
</Text>
|
|
</View>
|
|
<GradientButton
|
|
title={publishButtonLabel}
|
|
onPress={handleConfirmPublish}
|
|
disabled={publishDisabled}
|
|
/>
|
|
|
|
{hasYoutubePublication && youtubeUrl && (
|
|
<BorderGradientButton
|
|
title="Voir la vidéo sur YouTube"
|
|
onPress={handleOpenYoutube}
|
|
disabled={saving || isPublishing}
|
|
/>
|
|
)}
|
|
{hasYoutubePublication && (
|
|
<BorderGradientButton
|
|
title="Réinitialiser la publication"
|
|
onPress={handleResetPublication}
|
|
disabled={saving || isPublishing}
|
|
/>
|
|
)}
|
|
</View>
|
|
</View>
|
|
</Page>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
consentContainer: {
|
|
gap: 6,
|
|
},
|
|
consentDescription: {
|
|
fontSize: 13,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
color: Palette.white,
|
|
opacity: 0.8,
|
|
},
|
|
})
|
|
|
|
export default PublishYoutube
|