import { Dialog, Transition } from "@headlessui/react"; import { Fragment, useCallback, useState } from "react"; import { FiShare } from "react-icons/fi"; import { GrTwitter, GrReddit } from "react-icons/gr"; import styled from "styled-components"; import { InferenceResult } from "../types"; interface ShareProps { inferenceResults: InferenceResult[]; nowPlayingResult: InferenceResult; } const ModalContainer = styled.div` position: absolute; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; `; export default function Share({ inferenceResults, nowPlayingResult, }: ShareProps) { const [open, setOpen] = useState(false); var classNameCondition = ""; if (open) { classNameCondition = "fixed z-20 top-24 right-4 md:top-28 md:right-8 bg-sky-400 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-white text-2xl hover:bg-sky-500 hover:drop-shadow-2xl"; } else { classNameCondition = "fixed z-20 top-24 right-4 md:top-28 md:right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-sky-900 text-2xl hover:text-white hover:bg-sky-600 hover:drop-shadow-2xl"; } // function to copy link to moment in song to the clipboard function copyLinkToClipboard(secondsAgo: number) { // use generateLink to generate the link const link = generateLink(secondsAgo); navigator.clipboard.writeText(link); } function getActiveResult() { if (!nowPlayingResult) { if (inferenceResults.length == 0) { return null; } return inferenceResults[0]; } else { return nowPlayingResult; } } // function to generate a link to a the moment in the song based on the played clips, input variable is how many seconds ago const generateLink = useCallback( (secondsAgo: number) => { var prompt; var seed; var denoising; var maskImageId; var seedImageId; var guidance; var numInferenceSteps; var alphaVelocity; const result = nowPlayingResult ? nowPlayingResult : inferenceResults[0]; if (!result) { return window.location.href; } else { var selectedInput: InferenceResult["input"]; if (secondsAgo == 0) { selectedInput = result.input; } else { var selectedCounter = result.counter - secondsAgo / 5; selectedInput = inferenceResults.find( (result) => result.counter == selectedCounter )?.input; if (!selectedInput) { // TODO: ideally don't show the button in this case... return window.location.href; } } // TODO: Consider only including in the link the things that are different from the default values prompt = selectedInput.start.prompt; seed = selectedInput.start.seed; denoising = selectedInput.start.denoising; maskImageId = selectedInput.mask_image_id; seedImageId = result.input.seed_image_id; // TODO, selectively add these based on whether we give user option to change them // guidance = result.input.guidance // numInferenceSteps = result.input.num_inference_steps // alphaVelocity = result.input.alpha_velocity } var baseUrl = window.location.origin + "/?"; if (prompt != null) { var promptString = "&prompt=" + prompt; } else { promptString = ""; } if (seed != null) { var seedString = "&seed=" + seed; } else { seedString = ""; } if (denoising != null) { var denoisingString = "&denoising=" + denoising; } else { denoisingString = ""; } if (maskImageId != null) { var maskImageIdString = "&maskImageId=" + maskImageId; } else { maskImageIdString = ""; } if (seedImageId != null) { var seedImageIdString = "&seedImageId=" + seedImageId; } else { seedImageIdString = ""; } if (guidance != null) { var guidanceString = "&guidance=" + guidance; } else { guidanceString = ""; } if (numInferenceSteps != null) { var numInferenceStepsString = "&numInferenceSteps=" + numInferenceSteps; } else { numInferenceStepsString = ""; } if (alphaVelocity != null) { var alphaVelocityString = "&alphaVelocity=" + alphaVelocity; } else { alphaVelocityString = ""; } // Format strings to have + in place of spaces for ease of sharing, note this is only necessary for prompts currently promptString = promptString.replace(/ /g, "+"); // create url string with the variables above combined var shareUrl = baseUrl + promptString + seedString + denoisingString + maskImageIdString + seedImageIdString + guidanceString + numInferenceStepsString + alphaVelocityString; return shareUrl; }, [nowPlayingResult, inferenceResults] ); const getRedditLink = useCallback(() => { if (inferenceResults.length == 0) { return null; } const result = nowPlayingResult ? nowPlayingResult : inferenceResults[0]; const encodedPrompt = encodeURIComponent(result.input.start.prompt); const encodedUrl = encodeURIComponent(generateLink(0)); return `https://www.reddit.com/r/riffusion/submit?title=Check+out+this+%23riffusion+prompt:+${encodeURI( '"' )}${encodedPrompt}${encodeURI('"')}&url=${encodedUrl}`; }, [nowPlayingResult, inferenceResults, generateLink]); const getTwitterLink = useCallback(() => { if (inferenceResults.length == 0) { return null; } const result = nowPlayingResult ? nowPlayingResult : inferenceResults[0]; const encodedPrompt = encodeURIComponent(result.input.start.prompt); const encodedUrl = encodeURIComponent(generateLink(0)); return `https://twitter.com/intent/tweet?&text=Check+out+this+%23riffusion+prompt:+${encodeURI( '"' )}${encodedPrompt}${encodeURI('"')}${encodeURI("\n\n")}${encodedUrl}`; }, [nowPlayingResult, inferenceResults, generateLink]); return ( <> setOpen(true)} > setOpen(false)} > Share your riff { window.open(getTwitterLink(), "_blank"); }} /> { window.open(getRedditLink(), "_blank"); }} /> {!getActiveResult() && ( )} {getActiveResult() && ( )} Your browser does not support audio. { setOpen(false); }} > Cancel { copyLinkToClipboard(0); setOpen(false); }} > 🔗 Copy link to current moment > ); }