Skip to content

Commit

Permalink
Merge pull request #33 from chimobi-justice/ft/text-to-speech
Browse files Browse the repository at this point in the history
Text to speech to articles
  • Loading branch information
chimobi-justice authored Oct 12, 2024
2 parents 624b17e + 9994a04 commit 1af6e79
Show file tree
Hide file tree
Showing 42 changed files with 523 additions and 530 deletions.
51 changes: 48 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@emotion/styled": "^11.11.5",
"@fontsource/open-sans": "^5.1.0",
"@fontsource/raleway": "^5.1.0",
"@phntms/react-share": "^1.0.2-rc1",
"@tanstack/react-query": "^5.50.1",
"@tanstack/react-query-devtools": "^5.56.2",
"axios": "^1.7.2",
Expand Down
14 changes: 2 additions & 12 deletions src/components/ArticleCard/Articles.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
import { FunctionComponent } from 'react'
import { Link } from 'react-router-dom'
import {
Avatar,
Box,
Card,
CardBody,
Flex,
Heading,
Image,
Text,
Tooltip
} from '@chakra-ui/react'
import { Avatar, Box, Card, CardBody, Flex, Heading, Image, Text, Tooltip } from '@chakra-ui/react'
import { CiEdit } from 'react-icons/ci'
import { MdDeleteOutline } from 'react-icons/md'
import { BsSave } from 'react-icons/bs'
Expand Down Expand Up @@ -157,7 +147,7 @@ const ArticlesCard: FunctionComponent<IProps> = ({
_hover={{ textDecoration: "underline" }}
onClick={followUser}
>
{is_following ? "following" : "follow"}
{is_following ? "unfollow" : "follow"}
</Text>
)}

Expand Down
19 changes: 10 additions & 9 deletions src/components/NavBar/navBarLg.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const NavBarLg: FunctionComponent = () => {
as="nav"
bg={colors.secondary}
display={{ base: 'none', md: 'flex' }}
borderBottom={"2px solid #f1f1f1"}
>
<Container maxW={"container.xl"}>
<Box
Expand Down Expand Up @@ -88,11 +89,11 @@ const NavBarLg: FunctionComponent = () => {
</Link>

{user ? (
<Box>
<ChakraMenu>
<Box display={"block"}>
<ChakraMenu isLazy>
{({ isOpen }) => (
<>
<MenuButton as={Box} cursor="pointer">
<MenuButton as={Box} cursor="pointer" display={"block"}>
<Box display={"flex"} alignItems={"center"} gap="20px">
<Box display={"flex"} alignItems={"center"} gap="12px">
<Avatar
Expand All @@ -108,33 +109,33 @@ const NavBarLg: FunctionComponent = () => {
>
{user?.data?.fullname}
</Text>
</Box>
</Box>
</Box>
{isOpen ? <IoIosArrowUp /> : <IoIosArrowDown />}
</Box>
</MenuButton>
<MenuList>
<Link to={`/${user?.data?.username}`} style={{display: "block"}}>
<Link to={`/${user?.data?.username}`} style={{ display: "block" }}>
<MenuItem color={"black"}>
<GoPerson style={{ marginRight: "4px" }} /> Your Profile
</MenuItem>
</Link>
<Link to={`/me/articles/${user?.data?.username}`} style={{display: "block"}}>
<Link to={`/me/articles/${user?.data?.username}`} style={{ display: "block" }}>
<MenuItem color={"black"}>
<RiArticleFill style={{ marginRight: "4px" }} /> Your Articles
</MenuItem>
</Link>
<Link to={`/me/threads/${user?.data?.username}`} style={{display: "block"}}>
<Link to={`/me/threads/${user?.data?.username}`} style={{ display: "block" }}>
<MenuItem color={"black"}>
<RiChatThreadLine style={{ marginRight: "4px" }} /> Your Threads
</MenuItem>
</Link>
<Link to={`/${user?.data?.username}/reading-list`} style={{display: "block"}}>
<Link to={`/${user?.data?.username}/reading-list`} style={{ display: "block" }}>
<MenuItem color={"black"}>
<CiViewList style={{ marginRight: "4px" }} /> Reading List
</MenuItem>
</Link>
<Link to="/me/settings/account/edit" style={{display: "block"}}>
<Link to="/me/settings/account/edit" style={{ display: "block" }}>
<MenuItem color={"black"}>
<IoSettingsOutline style={{ marginRight: "4px" }} /> Settings
</MenuItem>
Expand Down
1 change: 1 addition & 0 deletions src/components/NavBar/navBarSm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const NavBarSm: FunctionComponent = () => {
p="8px"
w="100%"
display={{ base: 'flex', md: 'none' }}
borderBottom={"2px solid #f1f1f1"}
>
<Link to="/">
<Heading
Expand Down
6 changes: 3 additions & 3 deletions src/components/ShowLoginModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FunctionComponent } from 'react'
import { Modal, ModalBody, ModalContent, ModalHeader, ModalOverlay } from '@chakra-ui/react'
import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay } from '@chakra-ui/react'
import { Formik } from 'formik'

import { LoginForm } from '@components/index'
Expand Down Expand Up @@ -32,13 +32,13 @@ const ShowLoginModal: FunctionComponent<IProps> = ({ isOpen, onClose }) => {
/>
<ModalContent>
<ModalBody>
<ModalHeader textAlign={"center"}>Sign in to paticipate</ModalHeader>
<ModalHeader textAlign={"center"}>Log In</ModalHeader>
<ModalCloseButton />

<Formik
initialValues={initialValues}
onSubmit={handleSignin}
validationSchema={signInValidataionSchema}

>
{({ handleSubmit, errors, touched }) => (
<LoginForm
Expand Down
80 changes: 80 additions & 0 deletions src/components/TextSpeech/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Flex, Text, Tooltip } from '@chakra-ui/react'
import { FunctionComponent, useEffect, useState } from 'react'
import { IoMicCircleSharp, IoPlayCircle, IoPlayCircleOutline } from 'react-icons/io5'

interface TextSpeechProps {
title?: string;
content?: string;
}

const TextSpeech: FunctionComponent<TextSpeechProps> = ({ title, content }) => {
const [isSpeaking, setIsSpeaking] = useState(false);
const [isPaused, setIsPaused] = useState(false);
const [utterance, setUtterance] = useState<SpeechSynthesisUtterance | null>(null);

const synth = window.speechSynthesis;

useEffect(() => {
const newUtterance = new SpeechSynthesisUtterance(`${title} ${content}`);
newUtterance.lang = "en-US";
setUtterance(newUtterance);

return () => {
synth.cancel();
}
}, [title, content]);


const handlePlay = () => {
if (utterance && !isSpeaking) {
synth.speak(utterance);
setIsSpeaking(true);
setIsPaused(false);
} else if (isPaused) {
synth.resume();
setIsPaused(false);
}
}

const handlePause = () => {
if (synth.speaking && !isPaused) {
synth.pause();
setIsPaused(true);
}
}

const handleStop = () => {
synth.cancel();
setIsSpeaking(false);
setIsPaused(false);
}

return (
<Flex gap={3} alignItems={"center"}>
{!isSpeaking || isPaused ? (
<Tooltip label={isPaused ? 'Resume' : 'Play'} placement="top">
<Text as="span">
<IoPlayCircleOutline size="21px" onClick={handlePlay} cursor="pointer" />
</Text>
</Tooltip>
): (
<Tooltip label={"Stop Listening"} placement="top">
<Text as="span">
<IoPlayCircle size="25px" onClick={handleStop} cursor="pointer" />
</Text>
</Tooltip>
)}

{isSpeaking && !isPaused && (
<Tooltip label={"Pause Listening"} placement="top">
<Text as="span">

<IoMicCircleSharp size={"25px"} onClick={handlePause} cursor="pointer" />
</Text>
</Tooltip>
)}
</Flex>
)
}

export default TextSpeech;
2 changes: 2 additions & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Loading from '@components/Loading'
import LoginForm from '@components/LoginForm'
import RegisterForm from '@components/RegisterForm'
import ShowLoginModal from '@components/ShowLoginModal'
import TextSpeech from '@components/TextSpeech'

export {
Alert,
Expand All @@ -44,4 +45,5 @@ export {
LoginForm,
RegisterForm,
ShowLoginModal,
TextSpeech,
}
1 change: 0 additions & 1 deletion src/hooks/article/useCreateArticleComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const useCreateArticleComment = () => {
successNotification(data.message);

queryClient.invalidateQueries({ queryKey: ['articles']});

queryClient.invalidateQueries({ queryKey: ['article']});
},
onError: (error: any) => {
Expand Down
2 changes: 0 additions & 2 deletions src/hooks/article/useCreateArticleDisLike.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ export const useCreateArticleDisLike = () => {
mutationFn: createArticleDisLike,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['articles'] });

queryClient.invalidateQueries({ queryKey: ['article'] });

queryClient.invalidateQueries({ queryKey: ['public-author-article'] });
},
onError: (error: any) => {
Expand Down
2 changes: 0 additions & 2 deletions src/hooks/article/useCreateArticleLike.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ export const useCreateArticleLike = () => {
mutationFn: createArticleLike,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['articles'] });

queryClient.invalidateQueries({ queryKey: ['article'] });

queryClient.invalidateQueries({ queryKey: ['public-author-article'] });
},
onError: (error: any) => {
Expand Down
3 changes: 1 addition & 2 deletions src/hooks/article/useCreateSaveArticles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ export const useCreateSaveArticle = () => {
onSuccess: (data) => {
successNotification(data?.message)

queryClient.invalidateQueries({ queryKey: ['article'] });
queryClient.invalidateQueries({ queryKey: ['articles'] });

queryClient.invalidateQueries({ queryKey: ['saved-articles'] });

queryClient.invalidateQueries({ queryKey: ['recommented-articles'] });
},
onError: (error: any) => {
Expand Down
1 change: 0 additions & 1 deletion src/hooks/article/useDeleteArticle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const useDeleteArticle = () => {
successNotification(data.message);

queryClient.invalidateQueries({ queryKey: ['articles'] });

queryClient.invalidateQueries({ queryKey: ['article'] });
},
onError: (error: any) => {
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/article/useDeleteSavaArticles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const useDeleteSaveArticle = () => {
onSuccess: (data) => {
successNotification(data?.message)

queryClient.invalidateQueries({ queryKey: ['article'] });

queryClient.invalidateQueries({ queryKey: ['articles'] });

queryClient.invalidateQueries({ queryKey: ['saved-articles'] });
Expand Down
4 changes: 1 addition & 3 deletions src/hooks/auth/useSignOut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ export const useSignOut = () => {
mutationFn: signoutUser,
onSuccess: (data) => {
successNotification(data.message);
queryClient.invalidateQueries({
queryKey: ['user']
})
queryClient.invalidateQueries({ queryKey: ['user'] })

localStorage.removeItem('ucType_');

Expand Down
1 change: 0 additions & 1 deletion src/hooks/thread/useCreateThreadComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export const useCreateThreadComment = () => {
successNotification(data.message);

queryClient.invalidateQueries({ queryKey: ['threads'] });

queryClient.invalidateQueries({ queryKey: ['thread'] })
},
onError: (error: any) => {
Expand Down
Loading

0 comments on commit 1af6e79

Please sign in to comment.