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%);
+ }
+}