diff --git a/src/components/LoginButton.tsx b/src/components/LoginButton.tsx index 081bec20..9172a3ae 100644 --- a/src/components/LoginButton.tsx +++ b/src/components/LoginButton.tsx @@ -82,9 +82,9 @@ export const LoginButton = observer(function LoginButton() { width="100%" onClick={action(() => { userStore.me = user; - experienceStore.openEmptyExperience(router); if (store.context === "experienceEditor") { uiStore.showingOpenExperienceModal = true; + experienceStore.openEmptyExperience(router); } onClose(); })} @@ -112,7 +112,9 @@ export const LoginButton = observer(function LoginButton() { username: newUsername, }); userStore.me = newUser; - experienceStore.openEmptyExperience(router); + if (store.context === "experienceEditor") { + experienceStore.openEmptyExperience(router); + } onClose(); })} > diff --git a/src/components/Menu/MenuBar.tsx b/src/components/Menu/MenuBar.tsx index 45bc00a5..ec598164 100644 --- a/src/components/Menu/MenuBar.tsx +++ b/src/components/Menu/MenuBar.tsx @@ -107,6 +107,11 @@ export const MenuBar = observer(function MenuBar() { > {store.experienceName} + {store.experienceUser && ( + + by {store.experienceUser.username} + + )} {store.context === "experienceEditor" && !store.hasSaved && !store.experienceId && ( @@ -193,6 +198,7 @@ export const MenuBar = observer(function MenuBar() { icon={} command="⌘S" onClick={() => saveExperience()} + isDisabled={!store.canEditExperience} > Save diff --git a/src/components/PlaylistEditor/PlaylistEditor.tsx b/src/components/PlaylistEditor/PlaylistEditor.tsx index 124cccf1..b7f80ebd 100644 --- a/src/components/PlaylistEditor/PlaylistEditor.tsx +++ b/src/components/PlaylistEditor/PlaylistEditor.tsx @@ -22,7 +22,7 @@ import { BiShuffle } from "react-icons/bi"; import { ImLoop } from "react-icons/im"; import { trpc } from "@/src/utils/trpc"; import { PlaylistNameEditable } from "@/src/components/PlaylistEditor/PlaylistNameEditable"; -import { useEffect } from "react"; +import { useEffect, useRef } from "react"; import { FaPlus } from "react-icons/fa"; import { useRouter } from "next/router"; @@ -48,16 +48,17 @@ export const PlaylistEditor = observer(function PlaylistEditor() { ); useEffect(() => { - runInAction(() => { - // this is very hacky and I hate it but it works - if (data?.playlist) playlistStore.selectedPlaylist = data.playlist; - }); + // Once the playlist is fetched, set it as the selected playlist + if (data?.playlist) + runInAction(() => (playlistStore.selectedPlaylist = data.playlist)); }, [playlistStore, data?.playlist]); + const selectedInitialExperience = useRef(false); useEffect(() => { - if (!data?.playlistExperiences.length) return; - if (store.experienceName && store.experienceName !== "untitled") return; - // once experiences are fetched, load the first experience in the playlist + if (!data?.playlistExperiences.length || selectedInitialExperience.current) + return; + selectedInitialExperience.current = true; + // Once the experiences are fetched and if we have not done so already, select the first experience experienceStore.load(data.playlistExperiences[0].name); }, [store.experienceName, experienceStore, data?.playlistExperiences]); diff --git a/src/components/PlaylistEditor/PlaylistEditorPage.tsx b/src/components/PlaylistEditor/PlaylistEditorPage.tsx index 9e0035bf..d71d8e46 100644 --- a/src/components/PlaylistEditor/PlaylistEditorPage.tsx +++ b/src/components/PlaylistEditor/PlaylistEditorPage.tsx @@ -20,7 +20,7 @@ export const PlaylistEditorPage = observer(function PlaylistEditorPage() { }, [store, store.initializationState]); return ( - + { - if (!playlists || playlists.length === 0 || playlistStore.selectedPlaylist) - return; - runInAction(() => { - playlistStore.selectedPlaylist = playlists[0]; - }); + if (!playlists?.length || selectedInitialPlaylist.current) return; + selectedInitialPlaylist.current = true; + // Once the playlists are fetched and if we have not done so already, select the first playlist + runInAction(() => (playlistStore.selectedPlaylist = playlists[0])); }, [playlists, playlistStore]); if (isError) return null; @@ -104,7 +104,7 @@ export const PlaylistLibrary = observer(function PlaylistLibrary() { All playlists - {isFetching ? ( + {isPending ? ( ) : ( playlists?.map((playlist) => ( diff --git a/src/components/Timeline/SongMarquee.tsx b/src/components/Timeline/SongMarquee.tsx new file mode 100644 index 00000000..82c8fb46 --- /dev/null +++ b/src/components/Timeline/SongMarquee.tsx @@ -0,0 +1,26 @@ +import { observer } from "mobx-react-lite"; +import { Box } from "@chakra-ui/react"; +import { useStore } from "@/src/types/StoreContext"; +import styles from "@/styles/SongMarquee.module.css"; + +export const SongMarquee = observer(function SongMarquee() { + const { audioStore } = useStore(); + const { selectedSong } = audioStore; + + return ( + + + {selectedSong.artist} - {selectedSong.name} . . . .{" "} + {selectedSong.artist} - {selectedSong.name} . . . . + + + ); +}); diff --git a/src/components/Timeline/TimerAndWaveform.tsx b/src/components/Timeline/TimerAndWaveform.tsx index a7d70d74..389a4742 100644 --- a/src/components/Timeline/TimerAndWaveform.tsx +++ b/src/components/Timeline/TimerAndWaveform.tsx @@ -5,6 +5,7 @@ import { LazyWavesurferWaveform } from "@/src/components/Wavesurfer/LazyWavesurf import { MAX_TIME } from "@/src/utils/time"; import { TimerReadout } from "@/src/components/Timeline/TimerReadout"; import { TimerControls } from "@/src/components/Timeline/TimerControls"; +import { SongMarquee } from "@/src/components/Timeline/SongMarquee"; export const TimerAndWaveform = observer(function TimerAndWaveform() { const store = useStore(); @@ -36,7 +37,9 @@ export const TimerAndWaveform = observer(function TimerAndWaveform() { height="80px" zIndex={18} bgColor="gray.500" + overflow="hidden" > + {store.context === "playlistEditor" && } diff --git a/src/components/Timeline/TimerControls.tsx b/src/components/Timeline/TimerControls.tsx index fd11f999..aeed7dc0 100644 --- a/src/components/Timeline/TimerControls.tsx +++ b/src/components/Timeline/TimerControls.tsx @@ -9,6 +9,7 @@ export const TimerControls = observer(function TimerControls() { const store = useStore(); const { audioStore, playlistStore } = store; const playing = audioStore.audioState === "playing"; + const showSkipButtons = store.context === "experienceEditor"; return ( @@ -59,30 +60,32 @@ export const TimerControls = observer(function TimerControls() { /> - - - } - onClick={action(() => audioStore.skip(-10))} - /> - } - onClick={action(() => audioStore.skip(10))} - /> - - + {showSkipButtons && ( + + + } + onClick={action(() => audioStore.skip(-10))} + /> + } + onClick={action(() => audioStore.skip(10))} + /> + + + )} ); }); diff --git a/src/types/ExperienceStore.ts b/src/types/ExperienceStore.ts index e9b0b904..92a33005 100644 --- a/src/types/ExperienceStore.ts +++ b/src/types/ExperienceStore.ts @@ -18,12 +18,12 @@ export class ExperienceStore { makeAutoObservable(this); } - // Open an experience by experience name + // Open an experience in the experience editor by experience name openExperience = (router: NextRouter, experienceName: string) => { router.push(`/experience/${experienceName}`); }; - // Open an empty experience + // Open an empty experience in the experience editor openEmptyExperience = (router: NextRouter) => { router.push("/experience/untitled"); }; diff --git a/src/types/PlaylistStore.ts b/src/types/PlaylistStore.ts index 7d6e6655..e4d8dc01 100644 --- a/src/types/PlaylistStore.ts +++ b/src/types/PlaylistStore.ts @@ -56,9 +56,9 @@ export class PlaylistStore { } await this.store.experienceStore.loadById(experienceId); - runInAction(() => { - this.store.audioStore.audioState = "playing"; - }); + + this.store.audioStore.setTimeWithCursor(0); + this.store.play(); }; playPreviousExperience = async () => { diff --git a/styles/SongMarquee.module.css b/styles/SongMarquee.module.css new file mode 100644 index 00000000..68267a5f --- /dev/null +++ b/styles/SongMarquee.module.css @@ -0,0 +1,12 @@ +.marquee { + animation: advance 8s linear infinite; +} + +@keyframes advance { + from { + transform: translateX(0px); + } + to { + transform: translateX(-50%); + } +}