diff --git a/README.MD b/README.MD index 004a575..46c8ccd 100644 --- a/README.MD +++ b/README.MD @@ -9,9 +9,9 @@ Stunning-story is an open source website that provides a digital interface for playing and creating gamebooks. Gamebooks are interactive novels where the reader makes choices that determine the outcome of the story. The website allows users to play existing gamebooks or create their own using a user-friendly interface. The scope of the project includes providing an easy-to-use platform for gamebook enthusiasts to play and create their own stories. The goal of the website is to be accessible to both experienced gamebook creators and those new to the format, providing a platform for players and creators to share and experience a wide range of interactive stories. -## A Ui to play a gamebook Stories: +## Play: -* The gamebook UI is a digital interface that allows users to interact with a gamebook story. It's includes features such as a text-based narrative, choices for the user to make, and the ability to track progress through the story. +* The gamebook UI is a digital interface that allows users to interact with a gamebook story. It's includes features such as a text-based narrative, choices for the user to make, and the ability to track progress through the story. * The digital interface for playing gamebooks is the interface that users interact with when they are reading and playing a gamebook. It includes features such as a navigation system for moving through the different sections of the gamebook, a display for the text and media elements of the story, and a way for the user to make choices and see the outcome of those choices. * It also include features such as bookmarks to save the user's progress, the ability to go back to previous choices, and settings for adjusting the appearance of the interface, such as text size and background color. @@ -20,7 +20,7 @@ The goal of the website is to be accessible to both experienced gamebook creator -## A Builder to build gamebook Stoies: +## Build: * The builder allows users to create their own gamebooks. It is a user-friendly interface that guides the user through the process of creating a gamebook, from writing the story to adding choices and determining the outcome of those choices. @@ -37,6 +37,21 @@ The goal of the website is to be accessible to both experienced gamebook creator ``` git clone https://github.com/O-Plums/stunning-story +vim dev.env +``` +```bash +export accessKeyId=key +export secretAccessKey=key +export GOOGLE_CLIENT_ID=key +export GOOGLE_CLIENT_SECRET=key +export STRAPI_URL=http://localhost:1337 +export STRAPI_TOKEN=key +export DISCORD_CLIENT_ID=key +export DISCORD_CLIENT_SECRET=key +export SECRET=key +``` +``` +source dev.env ``` * Client: The front is build using [NextJS](https://nextjs.org/) and [tailwindcss](https://tailwindcss.com/) diff --git a/client/components/Diagram/index.tsx b/client/components/Diagram/index.tsx index 61d39f5..6cd82e6 100644 --- a/client/components/Diagram/index.tsx +++ b/client/components/Diagram/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ /* eslint-disable react/destructuring-assignment */ /* eslint-disable consistent-return */ import React, { useState, useEffect } from 'react'; @@ -13,6 +14,7 @@ import { import EditStory from '@components/Story/EditStory'; import Switch from '@components/Switch'; import useTranslation from 'next-translate/useTranslation'; +import { useRouter } from 'next/router'; import DisplayNodes from './displayNode'; import Target from './target'; @@ -25,6 +27,7 @@ A node can connect back to the story. */ export default function Diagram(props: any) { const { t } = useTranslation('common'); + const router = useRouter(); const [story, setStory] = useState(props.story); const updateXarrow = useXarrow(); @@ -179,32 +182,43 @@ export default function Diagram(props: any) { updateXarrow(); }} > -
- { - await updateStory({ - ...story, - publishedAt: !story.publishedAt ? new Date() : null, - }); - setStory({ - ...story, - publishedAt: !story.publishedAt ? new Date() : null, - }); +
+
+ { + await updateStory({ + ...story, + publishedAt: !story.publishedAt ? new Date() : null, + }); + setStory({ + ...story, + publishedAt: !story.publishedAt ? new Date() : null, + }); + }} + label={ + !story.publishedAt ? ( +

{t('builder.draft')}

+ ) : ( +

{t('builder.published')}

+ ) + } + /> +
+
+
{storyGraph.length > 0 - && storyGraph.map((node: any) => node.outputs.map( - (output: any, outputIndex: number) => { - if (output.type === 'target') { - return ( - - {output.value} -

+ && storyGraph.map((node: any) => node.outputs.map((output: any, outputIndex: number) => { + if (output.type === 'target') { + return ( + + {output.value} +

)} - start={node.sourceId} - end={output.id} - color="green" - key={`${output.id}`} - /> - ); - } - if (output.type === 'node') { - return ( - - {output.canBeRemove && ( + start={node.sourceId} + end={output.id} + color="green" + key={`${output.id}`} + /> + ); + } + if (output.type === 'node') { + return ( + + {output.canBeRemove && ( { removeDupicateNode(node.sourceId, outputIndex); }} /> - )} -

- {output.value} -

-
+ )} +

+ {output.value} +

+
)} - start={node.sourceId} - end={output.sourceId} - color="purple" - key={`${output.id}`} - /> - ); - } + start={node.sourceId} + end={output.sourceId} + color="purple" + key={`${output.id}`} + /> + ); + } - return null; - }, - ))} + return null; + }))} {addNewNodeModal && ( diff --git a/client/components/Story/Reader/index.tsx b/client/components/Story/Reader/index.tsx index 6ce6f56..3626ba0 100644 --- a/client/components/Story/Reader/index.tsx +++ b/client/components/Story/Reader/index.tsx @@ -6,6 +6,9 @@ import { useRouter } from 'next/router'; import DeviceOrientation, { Orientation } from 'react-screen-orientation'; import { motion } from 'framer-motion'; import useTranslation from 'next-translate/useTranslation'; +import { SpeakerWaveIcon, SpeakerXMarkIcon } from '@heroicons/react/24/outline'; + +const audio = new Audio(); export default function Reader(props: any) { const { story } = props; @@ -13,6 +16,8 @@ export default function Reader(props: any) { const storyGraph = story.storyGraph || []; const [changeNode, setChangeNode] = useState(true); const [currentNode, setCurrentNode] = useState(storyGraph[0]); + const [isPlaying, setIsPlaying] = React.useState(false); + const router = useRouter(); const variants = { hidden: { opacity: 0, x: 200, y: 0 }, @@ -24,7 +29,12 @@ export default function Reader(props: any) { if (!changeNode) { setChangeNode(true); } + audio.src = story.audio; + return () => { + audio.pause(); + }; }, [changeNode]); + return ( @@ -43,7 +53,29 @@ export default function Reader(props: any) { transition={{ ztype: 'linear' }} className="h-3/5 lg:h-3/4 flex flex-col items-center justify-center relative" > -
+
+ {story.audio && isPlaying && ( +
+ { + setIsPlaying(!isPlaying); + audio.pause(); + }} + className="h-5 w-5 text-white" + /> +
+ )} + {story.audio && !isPlaying && ( +
+ { + setIsPlaying(!isPlaying); + audio.play(); + }} + className="h-5 w-5 text-white" + /> +
+ )}