Skip to content

Commit

Permalink
Merge branch 'social-media-sharing'
Browse files Browse the repository at this point in the history
  • Loading branch information
adhamali450 committed Oct 5, 2023
2 parents e45c8a6 + 15e7c52 commit 4e26813
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 101 deletions.
68 changes: 37 additions & 31 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import toast, { Toaster } from "react-hot-toast";
import { QueryClient, QueryClientProvider } from "react-query";
import { useWindowSize } from "@uidotdev/usehooks";

// import iconDownload from "@assets/icon-download.svg";
// import iconShare from "@assets/icon-share.svg";

import {
formatLyrics,
getLang,
Expand All @@ -20,8 +17,6 @@ import {
download,
} from "./utils";

import * as htmlToImage from "html-to-image";

import Searchbar from "@components/searchbar/Searchbar";
const SongPreview = lazy(() => import("@components/SongPreview"));
import SidePanel from "@components/SidePanel";
Expand All @@ -32,7 +27,10 @@ import PageLogo from "@compUtils/PageLogo";
import OptionsPanel from "@components/OptionsPanel";
const LyricsModal = lazy(() => import("@components/LyricsModal"));
import DownloadingOverlay from "@compUtils/DownloadingOverlay";
// import ShareModal from "@components/ShareModal";
import ShareModal from "@components/ShareModal";

import useCardToImage from "@/hooks/useCardToImage";
import useCopyImageToClipboard from "@/hooks/useCopyImageToClipboard";

const defaultLyricsData = {
lang: "",
Expand Down Expand Up @@ -77,6 +75,8 @@ function App() {

const { id, image } = song;

const copyToClipboard = useCopyImageToClipboard();

// Whenever a song is selected, fetch lyrics and colors
useEffect(() => {
if (objectEmpty(song)) return;
Expand Down Expand Up @@ -150,25 +150,11 @@ function App() {
};

const downloadHandler = () => {
if (cardRef.current == null) return;

setDownloading(true);
const scale = 2;

// Saving the card
const promise = htmlToImage
.toJpeg(cardRef.current, {
width: cardRef.current.offsetWidth * scale,
height: cardRef.current.offsetHeight * scale,
style: {
transform: `scale(${scale})`,
transformOrigin: "center",
},
skipAutoScale: true,
})
.then((base64) => {
download(base64, `lyrics-card-${id}.jpeg`);
});

const promise = useCardToImage(cardRef, 2).then((base64) =>
download(base64, `lyrics-card-${id ? id : "untitled"}.jpeg`)
);

// Showing a confirmation toast
toast
Expand All @@ -179,8 +165,27 @@ function App() {
})
.then(() => setDownloading(false))
.catch(() => setDownloading(false));
setShareModalOpen(false);
};

// setShareModalOpen(false);
const copyToClipboardHandler = () => {
setDownloading(true);

const promise = useCardToImage(cardRef, 2, 0.7).then((base64) =>
copyToClipboard(base64)
);

toast
.promise(promise, {
loading: "Copying...",
success: <p>Copied to clipboard!</p>,
error: <p>Could not copy. Please try again</p>,
})
.then(() => setDownloading(false))
.catch((e) => {
setDownloading(false);
console.error(e);
});
};

return (
Expand Down Expand Up @@ -231,7 +236,7 @@ function App() {
cardInfo={song}
lyricsData={lyricsData}
aspectRatio={cardAspectRatio}
onDownload={downloadHandler}
onSave={() => setShareModalOpen(true)}
/>
<DownloadingOverlay
className="opacity-75 bg-gray-300 card-size show-when-download"
Expand All @@ -241,11 +246,12 @@ function App() {
</div>
</CardStyleContext.Provider>

{/* <ShareModal
open={shareModalOpen}
onClosing={() => setShareModalOpen(false)}
downloadHandler={downloadHandler}
/> */}
<ShareModal
open={shareModalOpen}
onClosing={() => setShareModalOpen(false)}
downloadHandler={downloadHandler}
copyHandler={copyToClipboardHandler}
/>
</section>

<aside className="row-start-2 col-start-2 hidden lg:grid grid-rows-[120px_1fr] border border-gray-400 rounded-md overflow-auto">
Expand Down
1 change: 1 addition & 0 deletions src/assets/share/copy-to-clipboard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 7 additions & 5 deletions src/assets/share/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import download from "@assets/share/download.svg";
import facebook from "@assets/share/facebook.svg";
import messenger from "@assets/share/messenger.svg";
import whatsapp from "@assets/share/whatsapp.svg";
import twitter from "@assets/share/twitter.svg";
import download from "./download.svg";
import copyToClipboard from "./copy-to-clipboard.svg";
import facebook from "./facebook.svg";
import messenger from "./messenger.svg";
import whatsapp from "./whatsapp.svg";
import twitter from "./twitter.svg";

const shareIcons = {
download,
copyToClipboard,
facebook,
messenger,
whatsapp,
Expand Down
138 changes: 85 additions & 53 deletions src/components/ShareModal.jsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import React, { useState, useEffect } from "react";
import Sheet from "react-modal-sheet";
import {
shareToFacebook,
shareToTwitter,
shareToWhatsApp,
shareToMessenger,
} from "@utils/shareUtils";

import ModalSheet from "react-modal-sheet";
import { Global } from "@emotion/react";
import { SwipeableDrawer } from "@mui/material";
import useOnBackButton from "@hooks/useOnBackButton";

import iconShare from "@assets/icon-share.svg";
import icons from "@assets/share";
import { shadeColor } from "../utils";
import { shareToInstagram } from "../utils/shareUtils";

const ShareModal = ({
open = false,
onClosing = () => {},
getShareUrl,
copyHandler,
downloadHandler,
}) => {
const [isOpen, setIsOpen] = useState(open);
const [shareUrl, setShareUrl] = useState("");

useEffect(() => {
setIsOpen(open);
Expand Down Expand Up @@ -56,63 +54,97 @@ const ShareModal = ({
},
];

const handleShare = async (platform) => {
shareToMessenger(
"https://dl.dropboxusercontent.com/s/5c98fdgt13inhu9/lyrics-card-1499166.png"
);
};
const handleShare = async (platform) => {};

// Close modal on back button
useOnBackButton(() => {
setIsOpen(false);
});

const closeHandler = () => {
setIsOpen(false);
onClosing();
};

const iOS =
typeof navigator !== "undefined" &&
/iPad|iPhone|iPod/.test(navigator.userAgent);
return (
<Sheet isOpen={isOpen} onClose={closeHandler} snapPoints={["0.5"]}>
<Sheet.Container>
<ModalSheet.Header
pinned
className="xs:rounded-t-md"
onDirectionLock={closeHandler}
></ModalSheet.Header>
<Sheet.Content>
<div className="flex flex-col items-center justify-center w-full h-full">
<h1 className="text-xl">Download and share</h1>
<div className="mt-5 flex flex-col md:flex-row justify-center items-center">
{/* Download */}
<button
className="flex flex-row md:flex-col items-center gap-2 hover:bg-gray-200 rounded-md p-2"
onClick={downloadHandler}
>
<img src={icons.download} />
<span className="text-sm">Download</span>
</button>

<hr className="hidden md:inline-block bg-gray-300 w-[1px] h-[40px] mx-4" />

{/* Share to social media */}

<div className="gap-2 grid grid-cols-2 md:grid-cols-4">
{platforms.map((platform, index) => {
return (
<button
className="w-full h-full flex flex-row md:flex-col items-center gap-2 hover:bg-gray-200 rounded-md p-2"
key={platform.name}
onClick={() => handleShare(platform.name)}
>
<img src={platform.icon} />
<span className="text-sm">{platform.name}</span>
</button>
);
})}
<>
<Global
styles={{
".MuiDrawer-root > .MuiPaper-root": {
height: `calc(50vh)`,
overflow: "visible",
},
}}
/>
<SwipeableDrawer
anchor="bottom"
open={isOpen}
onClose={closeHandler}
onOpen={() => {}}
sx={{
".MuiDrawer-root > .MuiPaper-root": {
height: `50vh`,
overflow: "visible",
},
}}
variant="temporary"
disableBackdropTransition={!iOS}
disableDiscovery={iOS}
allowSwipeInChildren={true}
>
<div className="flex flex-col items-center justify-center w-full h-full">
<h1 className="text-xl">Download and share</h1>
<div className="mt-5 flex flex-col md:flex-row justify-center items-center">
{/* Download */}
<button
className="flex flex-row md:flex-col items-center gap-2 hover:bg-gray-200 rounded-md p-2"
onClick={downloadHandler}
>
<img src={icons.download} />
<span className="text-sm">Download</span>
</button>

<hr className="hidden md:inline-block bg-gray-300 w-[1px] h-[40px] mx-4" />

<button
className="flex flex-row md:flex-col items-center gap-2 hover:bg-gray-200 rounded-md p-2"
onClick={copyHandler}
>
<img src={icons.copyToClipboard} />
<span className="text-sm">Copy</span>
</button>

<hr className="hidden md:inline-block bg-gray-300 w-[1px] h-[40px] mx-4" />

{/* Share to social media */}

<div className="relative gap-2 grid grid-cols-2 md:grid-cols-4 pointer-events-none">
{platforms.map((platform, index) => {
return (
<button
className="w-full h-full flex flex-row md:flex-col items-center gap-2 hover:bg-gray-200 rounded-md p-2"
key={platform.name}
onClick={() => handleShare(platform.name)}
>
<img src={platform.icon} />
<span className="text-sm">{platform.name}</span>
</button>
);
})}

<div className="absolute inset-0 backdrop-blur-sm grid place-content-center">
<span className="px-3 py-1 text-black text-opacity-70 font-bold rounded-md bg-[#f2d62f] shadow-md">
soon
</span>
</div>
</div>
</div>
</Sheet.Content>
</Sheet.Container>

<Sheet.Backdrop onClick={closeHandler} />
</Sheet>
</div>
</SwipeableDrawer>
</>
);
};

Expand Down
5 changes: 1 addition & 4 deletions src/components/lyrics-card/LyricsCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ const dummyLyrics = [
const copyLyrics = (lyrics) => lyrics.map((inner) => [...inner]);

const LyricsCard = forwardRef(
(
{ cardInfo, lyricsData, aspectRatio = "1:1", onDownload = () => {} },
ref
) => {
({ cardInfo, lyricsData, aspectRatio = "1:1", onSave = () => {} }, ref) => {
let { title = "Song Title", artist = "Artist Name" } = cardInfo;

const { cardStyling } = useContext(CardStyleContext);
Expand Down
15 changes: 15 additions & 0 deletions src/hooks/useCardToImage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as htmlToImage from "html-to-image";

const useCardToImage = (cardRef, scale = 1, quality = 1) => {
return htmlToImage.toJpeg(cardRef.current, {
width: cardRef.current.offsetWidth * scale,
height: cardRef.current.offsetHeight * scale,
style: {
transform: `scale(${scale})`,
transformOrigin: "top left",
},
quality: quality,
});
};

export default useCardToImage;
17 changes: 17 additions & 0 deletions src/hooks/useCopyImageToClipboard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const useCopyImageToClipboard = () => {
return (base64) => {
// Convert base64 to blob
const byteCharacters = atob(base64.split(",")[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type: "image/png" });

const item = new ClipboardItem({ "image/png": blob });
navigator.clipboard.write([item]);
};
};

export default useCopyImageToClipboard;
8 changes: 0 additions & 8 deletions src/utils/shareUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,3 @@ export const shareToTwitter = (url, text) => {
)}&text=${encodeURIComponent(text)}`;
window.open(twUrl, "_blank");
};

// Function to share a URL on Instagram
export const shareToInstagram = (url) => {
const instaUrl = `https://www.instagram.com/share?url=${encodeURIComponent(
url
)}`;
window.open(instaUrl, "_blank");
};

0 comments on commit 4e26813

Please sign in to comment.